Ejemplo n.º 1
0
size_t SymbolTable::map_operand(bh_instruction& instr, size_t operand_idx)
{
    size_t arg_idx = ++(nsymbols_); // Candidate arg_idx if not reused

    if (bh_is_constant(&instr.operand[operand_idx])) {  // Constants
        if (BH_R123 != instr.constant.type) {           // Regular constants
            table_[arg_idx].const_data   = &(instr.constant.value);
            table_[arg_idx].etype        = bhtype_to_etype(instr.constant.type);
        } else {                                        // "Special" for BH_R123
            table_[arg_idx].etype        = UINT64;
            if (1 == operand_idx) {
                table_[arg_idx].const_data  = &(instr.constant.value.r123.start);
            } else if (2 == operand_idx) {
                table_[arg_idx].const_data  = &(instr.constant.value.r123.key);
            } else {
                throw runtime_error("THIS SHOULD NEVER HAPPEN!");
            }
        }
        table_[arg_idx].data         = &table_[arg_idx].const_data;
        table_[arg_idx].nelem        = 1;
        table_[arg_idx].ndim         = 1;
        table_[arg_idx].start        = 0;
        table_[arg_idx].shape        = instr.operand[operand_idx].shape;
        table_[arg_idx].shape[0]     = 1;
        table_[arg_idx].stride       = instr.operand[operand_idx].shape;
        table_[arg_idx].stride[0]    = 0;
        table_[arg_idx].layout       = SCALAR_CONST;
        table_[arg_idx].base         = NULL;
    } else {
        table_[arg_idx].const_data= NULL;
        table_[arg_idx].data     = &(bh_base_array(&instr.operand[operand_idx])->data);
        table_[arg_idx].etype    = bhtype_to_etype(bh_base_array(&instr.operand[operand_idx])->type);
        table_[arg_idx].nelem    = bh_base_array(&instr.operand[operand_idx])->nelem;
        table_[arg_idx].ndim     = instr.operand[operand_idx].ndim;
        table_[arg_idx].start    = instr.operand[operand_idx].start;
        table_[arg_idx].shape    = instr.operand[operand_idx].shape;
        table_[arg_idx].stride   = instr.operand[operand_idx].stride;

        table_[arg_idx].layout   = determine_layout(table_[arg_idx]);
        table_[arg_idx].base     = instr.operand[operand_idx].base;
    }

    //
    // Reuse operand identifiers: Detect if we have seen it before and reuse the name.
    // This is done by comparing the currently investigated operand (arg_idx)
    // with all other operands in the current scope [1,arg_idx[
    // Do remember that 0 is is not a valid operand and we therefore index from 1.
    // Also we do not want to compare with selv, that is when i == arg_idx.
    for(size_t i=1; i<arg_idx; ++i) {
        if (!equivalent(table_[i], table_[arg_idx])) {
            continue; // Not equivalent, continue search.
        }
        // Found one! Use it instead of the incremented identifier.
        --nsymbols_;
        arg_idx = i;
        break;
    }
    return arg_idx;
}
Ejemplo n.º 2
0
/* Communicate array data such that the processes can apply local computation.
 * NB: The process that owns the data and the process where the data is located
 *     must both call this function.
 *
 * @chunk          The local array chunk to communicate
 * @sending_rank   The rank of the sending process
 * @receiving_rank The rank of the receiving process, e.g. the process that should
 *                 apply the computation
 */
void comm_array_data(const bh_view &chunk, int sending_rank, int receiving_rank)
{
//    printf("comm_array_data %d => %d: ", sending_rank, receiving_rank);
//    bh_view v = chunk;
//    bh_pprint_array(&v);

    //Check if communication is even necessary
    if(sending_rank == receiving_rank)
        return;

    if(pgrid_myrank == receiving_rank)
    {
        //Schedule the receive message
        batch_schedule_comm(0, sending_rank, chunk);
    }
    else if(pgrid_myrank == sending_rank)
    {
        //We need to copy the local array view into a base array buffer.
        bh_view tmp_view = chunk;
        tmp_view.base = tmp_get_ary(bh_base_array(&chunk)->type,
                                    bh_nelements_nbcast(&chunk));
        tmp_view.start = 0;

        //Set a contiguous row-major stride while preserving the zero-strided
        //dimensions (i.e. preserving broadcasted dimensions).
        bh_intp s = 1;
        for(bh_intp i=chunk.ndim-1; i >= 0; --i)
        {
            if(tmp_view.stride[i] > 0)
            {
                tmp_view.stride[i] = s;
                s *= tmp_view.shape[i];
            }
        }

        //Tell the VEM to do the data copy.
        bh_view ops[] = {tmp_view, chunk};
        batch_schedule_inst(BH_IDENTITY, ops);

        //Schedule the send message
        batch_schedule_comm(1, receiving_rank, tmp_view);

        //Cleanup the local arrays
        batch_schedule_inst_on_base(BH_FREE, bh_base_array(&tmp_view));
        batch_schedule_inst_on_base(BH_DISCARD, bh_base_array(&tmp_view));
    }
}
Ejemplo n.º 3
0
/* Implements matrix multiplication */
bh_error bh_matmul(bh_instruction *instr, void* arg)
{
    bh_view *C = &instr->operand[0];
    bh_view *A = &instr->operand[1];
    bh_view *B = &instr->operand[2];

    //Make sure that the arrays memory are allocated.
    if(bh_data_malloc(A->base) != BH_SUCCESS)
        return BH_OUT_OF_MEMORY;
    if(bh_data_malloc(B->base) != BH_SUCCESS)
        return BH_OUT_OF_MEMORY;
    if(bh_data_malloc(C->base) != BH_SUCCESS)
        return BH_OUT_OF_MEMORY;

    switch (bh_base_array(C)->type)
    {
    	case BH_INT8:
		    return do_matmul<bh_int8>(A, B, C);
    	case BH_INT16:
		    return do_matmul<bh_int16>(A, B, C);
    	case BH_INT32:
		    return do_matmul<bh_int32>(A, B, C);
    	case BH_INT64:
		    return do_matmul<bh_int64>(A, B, C);
        case BH_UINT8:
		    return do_matmul<bh_uint8>(A, B, C);
    	case BH_UINT16:
		    return do_matmul<bh_uint16>(A, B, C);
    	case BH_UINT32:
	            return do_matmul<bh_uint32>(A, B, C);
    	case BH_UINT64:
		    return do_matmul<bh_uint64>(A, B, C);
    	case BH_FLOAT32:
		    return do_matmul<bh_float32>(A, B, C);
    	case BH_FLOAT64:
		    return do_matmul<bh_float64>(A, B, C);
        case BH_COMPLEX64:
            return do_matmul<std::complex<float> >(A, B, C);
        case BH_COMPLEX128:
            return do_matmul<std::complex<double> >(A, B, C);
        default:
            return BH_TYPE_NOT_SUPPORTED;
    }
}
Ejemplo n.º 4
0
int main()
{
    dispatch_msg *msg;

    timing_init();

    //Initiate the process grid
    pgrid_init();

    while(1)
    {
        //Receive the dispatch message from the master-process
        dispatch_reset();
        dispatch_recv(&msg);

        //Handle the message
        switch(msg->type)
        {
            case BH_CLUSTER_DISPATCH_INIT:
            {
                char *name = msg->payload;
                check_error(exec_init(name),__FILE__,__LINE__);
                break;
            }
            case BH_CLUSTER_DISPATCH_SHUTDOWN:
            {
                check_error(exec_shutdown(),__FILE__,__LINE__);
                return 0;
            }
            case BH_CLUSTER_DISPATCH_EXTMETHOD:
            {
                bh_opcode opcode = *((bh_opcode *)msg->payload);
                char *name = msg->payload+sizeof(bh_opcode);
                check_error(exec_extmethod(name, opcode),__FILE__,__LINE__);
                break;
            }
            case BH_CLUSTER_DISPATCH_EXEC:
            {
                //Get the size of the the serialized BhIR
                bh_intp bhir_size = *((bh_intp*) msg->payload);

                //Deserialize the BhIR
                bh_ir bhir = bh_ir(((char*)msg->payload)+sizeof(bh_intp), bhir_size);

                //The number of new arrays
                bh_intp *noa = (bh_intp *)(((char*)msg->payload)+sizeof(bh_intp)+bhir_size);
                //The list of new arrays
                dispatch_array *darys = (dispatch_array*)(noa+1); //number of new arrays

                //Insert the new array into the array store and the array maps
                std::stack<bh_base*> base_darys;
                for(bh_intp i=0; i < *noa; ++i)
                {
                    bh_base *ary = dispatch_new_slave_array(&darys[i].ary, darys[i].id);
                    base_darys.push(ary);
                }

                //Receive the dispatched array-data from the master-process
                dispatch_array_data(base_darys);

                //Update all instruction to reference local arrays
                for(uint64_t i=0; i < bhir.instr_list.size(); ++i)
                {
                    bh_instruction *inst = &bhir.instr_list[i];
                    int nop = bh_noperands(inst->opcode);
                    bh_view *ops = bh_inst_operands(inst);

                    //Convert all instructon operands
                    for(bh_intp j=0; j<nop; ++j)
                    {
                        if(bh_is_constant(&ops[j]))
                            continue;
                        bh_base *base = bh_base_array(&ops[j]);
                        assert(dispatch_slave_exist((bh_intp)base));
                        bh_base_array(&ops[j]) = dispatch_master2slave((bh_intp)base);
                    }
                }
                check_error(exec_execute(&bhir),__FILE__,__LINE__);
                break;
            }
            default:
                fprintf(stderr, "[VEM-CLUSTER] Slave (rank %d) "
                        "received unknown message type\n", pgrid_myrank);
                MPI_Abort(MPI_COMM_WORLD,BH_ERROR);
        }
    }

    timing_finalize();
    return BH_SUCCESS;
}