<commit_before>/*
 * Copyright 2011 <NAME> <<EMAIL>>
 *
 * This file is part of cphVB.
 *
 * cphVB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cphVB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with cphVB. If not, see <http://www.gnu.org/licenses/>.
 */
#include "bundler.hpp"
#include <iostream>
#include <map>

typedef cphvb_array* cphvb_array_ptr;

/**
 * Determines whether two operands are aligned.
 * Specifically whether the following meta-data is equal to one another:
 *
 * ndim, start, shape, and stride.
 *
 * NOTE: base is not checked for equality.
 *
 * @param op_l Some operand
 * @param op_r Some other operand to compare with
 *
 * @return True when aligned, false when they are not.
 *
 */
inline bool ops_aligned( cphvb_array_ptr op_l, cphvb_array_ptr op_r) {

    bool aligned = true;

    if ((op_l->ndim != op_r->ndim) || (op_l->start != op_r->start)) // Check dim and start
    {
        aligned = false;                                            // Incompatible dim or start

    } else {
                                                                    
        for(cphvb_intp i=0; i < op_l->ndim; i++)                    // Check shape and stride
        {
            if ((op_l->stride[i] != op_r->stride[i]) || (op_l->shape[i] != op_r->shape[i]))
            {                                                       
                aligned = false;                                    // Incompatible shape or stride
                break;                                              // Stop checking
            }
        }

        // Reaching this point means that the operands are aligned aka they have equal:
        // ndim, start, shape and stride.

    }

    return aligned;

}

/* Calculates the bundleable instructions.
 *
 * @inst The instruction list
 * @size Size of the instruction list
 * @return Number of consecutive bundable instructions.
 */
cphvb_intp bundle(cphvb_instruction *insts[], cphvb_intp size)
{

    std::multimap<cphvb_array_ptr, cphvb_array_ptr> ops;
    std::multimap<cphvb_array_ptr, cphvb_array_ptr> ops_out;
    std::multimap<cphvb_array_ptr, cphvb_array_ptr>::iterator it;
    std::pair< 
        std::multimap<cphvb_array_ptr, cphvb_array_ptr>::iterator, 
        std::multimap<cphvb_array_ptr, cphvb_array_ptr>::iterator
    > ret;

    bool do_fuse = true;                                            // Loop invariant
    cphvb_intp bundle_len = 0;                                      // Number of cons. bundl. instr.
                                                                    // incremented on each iteration

    int opcount = 0;                                                // Per-instruction variables
    cphvb_array_ptr op, base;                                       // re-assigned on each iteration.

    for(cphvb_intp i=0; ((do_fuse) && (i<size)); i++) {             // Go through the instructions...

        opcount = cphvb_operands(insts[i]->opcode);

                                                                    // Add operands to "kernel"
        op      = insts[i]->operand[0];
        base    = op->base == NULL ? op : op->base;
                                                                    // Add output operand
        ops.insert(     std::pair<cphvb_array_ptr, cphvb_array_ptr>( base, op ) );
        ops_out.insert( std::pair<cphvb_array_ptr, cphvb_array_ptr>( base, op ) );

        for(int j=1; j < opcount; j++) {                            // Add input operand(s)
            op      = insts[i]->operand[j];
            base    = op->base == NULL ? op : op->base;
            ops.insert( std::pair<cphvb_array_ptr, cphvb_array_ptr>( base, op ) );
        }
                                                                    //
                                                                    // Now check for collisions.
                                                                    //

        op      = insts[i]->operand[0];                             // Look at the output-operand
        base    = op->base == NULL ? op : op->base;

        ret = ops.equal_range( base );                              // Compare to kernel-operands.
        for(it = ret.first; it != ret.second; ++it) {
            if (!ops_aligned( op, (*it).second )) {
                do_fuse = false;
                break;
            }
        }
                                                                    
        for(int j=1; ((do_fuse) && (j<opcount)); j++) {             // Look at the input-operands

            op      = insts[i]->operand[j];
            base    = op->base == NULL ? op : op->base;

            ret = ops_out.equal_range( base );                      // Compare to kernel-output-operands
            for(it = ret.first; it != ret.second; ++it) {
                if (!ops_aligned( op, (*it).second )) {
                    do_fuse = false;
                    break;
                }
            }

        }

        if (do_fuse) {                                                  // Instruction is allowed
            bundle_len++;
        }

    }

    #ifdef DEBUG_BNDL
    if (bundle_len > 1) {

        std::cout << "BUNDLING " << size << " {" << std::endl;
        for(cphvb_intp i=0; ((do_fuse) && (i<size)); i++) {             // Go through the instructions...
            cphvb_instr_pprint( insts[i] );
        }
        std::cout << "} ops {" << std::endl << "  ";
        for(it = ops.begin(); it != ops.end(); it++)
        {
            std::cout << *it << ",";
        }
        std::cout << std::endl;
        std::cout << "} bundle len = [" << bundle_len << "]" << std::endl;
    }
    #endif

    if(bundle_len<1) {
        bundle_len = 1;
    }

    //bundle_len = 1; // This is just here until bundling is done...
    return bundle_len;

}<commit_msg>Bundable / Bundlable / Bundleable something ought to work :)<commit_after>/*
 * Copyright 2011 <NAME> <<EMAIL>>
 *
 * This file is part of cphVB.
 *
 * cphVB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cphVB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with cphVB. If not, see <http://www.gnu.org/licenses/>.
 */
#include "bundler.hpp"
#include <iostream>
#include <map>

typedef cphvb_array* cphvb_array_ptr;

/**
 * Determines whether two operands are aligned.
 * Specifically whether the following meta-data is equal to one another:
 *
 * ndim, start, shape, and stride.
 *
 * NOTE: base is not checked for equality.
 *
 * @param op_l Some operand
 * @param op_r Some other operand to compare with
 *
 * @return True when aligned, false when they are not.
 *
 */
inline bool ops_aligned( cphvb_array_ptr op_l, cphvb_array_ptr op_r) {

    bool aligned = true;

    if ((op_l->ndim != op_r->ndim) || (op_l->start != op_r->start)) // Check dim and start
    {
        aligned = false;                                            // Incompatible dim or start

    } else {
                                                                    
        for(cphvb_intp i=0; i < op_l->ndim; i++)                    // Check shape and stride
        {
            if ((op_l->stride[i] != op_r->stride[i]) || (op_l->shape[i] != op_r->shape[i]))
            {                                                       
                aligned = false;                                    // Incompatible shape or stride
                break;                                              // Stop checking
            }
        }

        // Reaching this point means that the operands are aligned aka they have equal:
        // ndim, start, shape and stride.

    }

    return aligned;

}

/**
 * Calculates the bundleable instructions.
 *
 * @param inst The instruction list
 * @param size Size of the instruction list
 * @return Number of consecutive bundleable instructions.
 *
 */
cphvb_intp bundle(cphvb_instruction *insts[], cphvb_intp size)
{

    std::multimap<cphvb_array_ptr, cphvb_array_ptr> ops;            // Operands in kernel
    std::multimap<cphvb_array_ptr, cphvb_array_ptr> ops_out;        // Output-operands in kernel
    std::multimap<cphvb_array_ptr, cphvb_array_ptr>::iterator it;   // it / ret = Iterators
    std::pair< 
        std::multimap<cphvb_array_ptr, cphvb_array_ptr>::iterator, 
        std::multimap<cphvb_array_ptr, cphvb_array_ptr>::iterator
    > ret;

    bool do_fuse = true;                                            // Loop invariant
    cphvb_intp bundle_len = 0;                                      // Number of cons. bundl. instr.
                                                                    // incremented on each iteration

    int opcount = 0;                                                // Per-instruction variables
    cphvb_array_ptr op, base;                                       // re-assigned on each iteration.

    for(cphvb_intp i=0; ((do_fuse) && (i<size)); i++)               // Go through the instructions...
    {

        opcount = cphvb_operands(insts[i]->opcode);
                                                                    //
        op      = insts[i]->operand[0];                             // Add operands to "kernel"
        base    = op->base == NULL ? op : op->base;                 //
                                                                    // - output operand
        ops.insert(     std::pair<cphvb_array_ptr, cphvb_array_ptr>( base, op ) );
        ops_out.insert( std::pair<cphvb_array_ptr, cphvb_array_ptr>( base, op ) );

        for(int j=1; j < opcount; j++)                              // - input operand(s)
        {
            op      = insts[i]->operand[j];
            base    = op->base == NULL ? op : op->base;
            ops.insert( std::pair<cphvb_array_ptr, cphvb_array_ptr>( base, op ) );
        }
                                                                    // Check for collisions
        op      = insts[i]->operand[0];                             // Look at the output-operand
        base    = op->base == NULL ? op : op->base;

        ret = ops.equal_range( base );                              // Compare to all kernel operands.
        for(it = ret.first; it != ret.second; ++it)
        {
            if (!ops_aligned( op, (*it).second ))
            {
                do_fuse = false;
                break;
            }
        }
                                                                    
        for(int j=1; ((do_fuse) && (j<opcount)); j++)               // Look at the input-operands
        {
            op      = insts[i]->operand[j];
            base    = op->base == NULL ? op : op->base;

            ret = ops_out.equal_range( base );                      // Compare to kernel-output-operands
            for(it = ret.first; it != ret.second; ++it)
            {
                if (!ops_aligned( op, (*it).second ))
                {
                    do_fuse = false;
                    break;
                }
            }

        }

        if (do_fuse)                                                // Instruction is allowed
        {
            bundle_len++;
        }

    }

    #ifdef DEBUG_BNDL
    if (bundle_len > 1)
    {

        std::cout << "BUNDLING " << size << " {" << std::endl;
        for(cphvb_intp i=0; ((do_fuse) && (i<size)); i++)           // Go through the instructions...
        {
            cphvb_instr_pprint( insts[i] );
        }
        std::cout << "} ops {" << std::endl << "  ";
        for(it = ops.begin(); it != ops.end(); it++)
        {
            std::cout << *it << ",";
        }
        std::cout << std::endl;
        std::cout << "} bundle len = [" << bundle_len << "]" << std::endl;
    }
    #endif

    if(bundle_len<1)
    {
        bundle_len = 1;
    }

    return bundle_len;

}
{'fraction_non_alphanumeric': 0.11032900980702309, 'fraction_numerical': 0.002768111357165454, 'mean_word_length': 1.315509979857169, 'pattern_counts': {'":': 0, '<': 101, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 76, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5791554', 'n_tokens_mistral': 3516, 'n_tokens_neox': 3394, 'n_words': 975}