Ejemplo n.º 1
0
static int frag_send (ompi_osc_pt2pt_module_t *module, ompi_osc_pt2pt_frag_t *frag)
{
    int count;

    count = (int)((uintptr_t) frag->top - (uintptr_t) frag->buffer);

    OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
                         "osc pt2pt: frag_send called to %d, frag = %p, count = %d",
                         frag->target, (void *) frag, count));

    OSC_PT2PT_HTON(frag->header, module, frag->target);
    return ompi_osc_pt2pt_isend_w_cb (frag->buffer, count, MPI_BYTE, frag->target, OSC_PT2PT_FRAG_TAG,
                                     module->comm, frag_send_cb, frag);
}
Ejemplo n.º 2
0
static inline int ompi_osc_pt2pt_rget_internal (void *origin_addr, int origin_count,
                                               struct ompi_datatype_t *origin_dt,
                                               int target,
                                               OPAL_PTRDIFF_TYPE target_disp,
                                               int target_count,
                                               struct ompi_datatype_t *target_dt,
                                               struct ompi_win_t *win, bool release_req,
                                               struct ompi_request_t **request)
{
    int ret, tag;
    ompi_osc_pt2pt_module_t *module = GET_MODULE(win);
    bool is_long_datatype = false;
    ompi_osc_pt2pt_frag_t *frag;
    ompi_osc_pt2pt_header_get_t *header;
    ompi_osc_pt2pt_sync_t *pt2pt_sync;
    size_t ddt_len, frag_len;
    char *ptr;
    const void *packed_ddt;
    ompi_osc_pt2pt_request_t *pt2pt_request;

    OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
                         "get: 0x%lx, %d, %s, %d, %d, %d, %s, %s",
                         (unsigned long) origin_addr, origin_count,
                         origin_dt->name, target, (int) target_disp,
                         target_count, target_dt->name, win->w_name));

    pt2pt_sync = ompi_osc_pt2pt_module_sync_lookup (module, target, NULL);
    if (OPAL_UNLIKELY(NULL == pt2pt_sync)) {
        return OMPI_ERR_RMA_SYNC;
    }

    /* gets are always request based, so that we know where to land the data */
    OMPI_OSC_PT2PT_REQUEST_ALLOC(win, pt2pt_request);

    pt2pt_request->internal = release_req;

    /* short-circuit case */
    if (0 == origin_count || 0 == target_count) {
        ompi_osc_pt2pt_request_complete (pt2pt_request, MPI_SUCCESS);
        *request = &pt2pt_request->super;
        return OMPI_SUCCESS;
    }

    /* optimize self communication. TODO: optimize local communication */
    if (ompi_comm_rank (module->comm) == target) {
        *request = &pt2pt_request->super;
        return ompi_osc_pt2pt_get_self (pt2pt_sync, origin_addr, origin_count, origin_dt,
                                        target_disp, target_count, target_dt,
                                        module, pt2pt_request);
    }

    pt2pt_request->type = OMPI_OSC_PT2PT_HDR_TYPE_GET;
    pt2pt_request->origin_addr = origin_addr;
    pt2pt_request->origin_count = origin_count;
    OMPI_DATATYPE_RETAIN(origin_dt);
    pt2pt_request->origin_dt = origin_dt;

    /* Compute datatype length.  Note that the datatype description
     * must fit in a single frag */
    ddt_len = ompi_datatype_pack_description_length(target_dt);

    frag_len = sizeof(ompi_osc_pt2pt_header_get_t) + ddt_len;
    ret = ompi_osc_pt2pt_frag_alloc(module, target, frag_len, &frag, &ptr, false, release_req);
    if (OMPI_SUCCESS != ret) {
        /* allocate space for the header plus space to store ddt_len */
        frag_len = sizeof(ompi_osc_pt2pt_header_get_t) + 8;
        ret = ompi_osc_pt2pt_frag_alloc(module, target, frag_len, &frag, &ptr, false, release_req);
        if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
            return OMPI_ERR_OUT_OF_RESOURCE;
        }

        is_long_datatype = true;
    }

    tag = get_tag (module);

    /* for bookkeeping the get is "outgoing" */
    ompi_osc_signal_outgoing (module, target, 1);

    if (!release_req) {
        /* wait for epoch to begin before starting rget operation */
        ompi_osc_pt2pt_sync_wait_expected (pt2pt_sync);
    }

    header = (ompi_osc_pt2pt_header_get_t*) ptr;
    header->base.type = OMPI_OSC_PT2PT_HDR_TYPE_GET;
    header->base.flags = 0;
    header->len = frag_len;
    header->count = target_count;
    header->displacement = target_disp;
    header->tag = tag;
    OSC_PT2PT_HTON(header, module, target);
    ptr += sizeof(ompi_osc_pt2pt_header_get_t);

    do {
        ret = ompi_datatype_get_pack_description(target_dt, &packed_ddt);
        if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
            break;
        }

        if (is_long_datatype) {
            /* the datatype does not fit in an eager message. send it seperately */
            header->base.flags |= OMPI_OSC_PT2PT_HDR_FLAG_LARGE_DATATYPE;

            OMPI_DATATYPE_RETAIN(target_dt);

            ret = ompi_osc_pt2pt_isend_w_cb ((void *) packed_ddt, ddt_len, MPI_BYTE,
                                            target, tag_to_target(tag), module->comm,
                                            ompi_osc_pt2pt_dt_send_complete, target_dt);
            if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
                break;
            }

            *((uint64_t *) ptr) = ddt_len;
            ptr += 8;
        } else {
            memcpy((unsigned char*) ptr, packed_ddt, ddt_len);
            ptr += ddt_len;
        }

        /* TODO -- store the request somewhere so we can cancel it on error */
        pt2pt_request->outstanding_requests = 1;
        ret = ompi_osc_pt2pt_irecv_w_cb (origin_addr, origin_count, origin_dt,
                                        target, tag_to_origin(tag), module->comm,
                                        NULL, ompi_osc_pt2pt_req_comm_complete, pt2pt_request);
    } while (0);

    if (OMPI_SUCCESS == ret) {
        header->base.flags |= OMPI_OSC_PT2PT_HDR_FLAG_VALID;
        *request = &pt2pt_request->super;
    }

    return ompi_osc_pt2pt_frag_finish(module, frag);
}