/* try to get a small message out on to the wire quickly */ static inline int mca_pml_ob1_send_inline (const void *buf, size_t count, ompi_datatype_t * datatype, int dst, int tag, int16_t seqn, ompi_proc_t *dst_proc, mca_bml_base_endpoint_t* endpoint, ompi_communicator_t * comm) { mca_pml_ob1_match_hdr_t match; mca_bml_base_btl_t *bml_btl; opal_convertor_t convertor; size_t size; int rc; bml_btl = mca_bml_base_btl_array_get_next(&endpoint->btl_eager); if( NULL == bml_btl->btl->btl_sendi) return OMPI_ERR_NOT_AVAILABLE; ompi_datatype_type_size (datatype, &size); if ((size * count) > 256) { /* some random number */ return OMPI_ERR_NOT_AVAILABLE; } if (count > 0) { /* initialize just enough of the convertor to avoid a SEGV in opal_convertor_cleanup */ OBJ_CONSTRUCT(&convertor, opal_convertor_t); /* We will create a convertor specialized for the */ /* remote architecture and prepared with the datatype. */ opal_convertor_copy_and_prepare_for_send (dst_proc->super.proc_convertor, (const struct opal_datatype_t *) datatype, count, buf, 0, &convertor); opal_convertor_get_packed_size (&convertor, &size); } else { size = 0; } mca_pml_ob1_match_hdr_prepare (&match, MCA_PML_OB1_HDR_TYPE_MATCH, 0, comm->c_contextid, comm->c_my_rank, tag, seqn); ob1_hdr_hton(&match, MCA_PML_OB1_HDR_TYPE_MATCH, dst_proc); /* try to send immediately */ rc = mca_bml_base_sendi (bml_btl, &convertor, &match, OMPI_PML_OB1_MATCH_HDR_LEN, size, MCA_BTL_NO_ORDER, MCA_BTL_DES_FLAGS_PRIORITY | MCA_BTL_DES_FLAGS_BTL_OWNERSHIP, MCA_PML_OB1_HDR_TYPE_MATCH, NULL); if (count > 0) { opal_convertor_cleanup (&convertor); } if (OPAL_UNLIKELY(OMPI_SUCCESS != rc)) { return rc; } return (int) size; }
static inline int create_iov_list(const void *addr, int count, ompi_datatype_t *datatype, ucx_iovec_t **ucx_iov, uint32_t *ucx_iov_count) { int ret = OMPI_SUCCESS; size_t size; bool done = false; opal_convertor_t convertor; uint32_t iov_count, iov_idx; struct iovec iov[OSC_UCX_IOVEC_MAX]; uint32_t ucx_iov_idx; OBJ_CONSTRUCT(&convertor, opal_convertor_t); ret = opal_convertor_copy_and_prepare_for_send(ompi_mpi_local_convertor, &datatype->super, count, addr, 0, &convertor); if (ret != OMPI_SUCCESS) { return ret; } (*ucx_iov_count) = 0; ucx_iov_idx = 0; do { iov_count = OSC_UCX_IOVEC_MAX; iov_idx = 0; done = opal_convertor_raw(&convertor, iov, &iov_count, &size); (*ucx_iov_count) += iov_count; (*ucx_iov) = (ucx_iovec_t *)realloc((*ucx_iov), (*ucx_iov_count) * sizeof(ucx_iovec_t)); if (*ucx_iov == NULL) { return OMPI_ERR_TEMP_OUT_OF_RESOURCE; } while (iov_idx != iov_count) { (*ucx_iov)[ucx_iov_idx].addr = iov[iov_idx].iov_base; (*ucx_iov)[ucx_iov_idx].len = iov[iov_idx].iov_len; ucx_iov_idx++; iov_idx++; } assert((*ucx_iov_count) == ucx_iov_idx); } while (!done); opal_convertor_cleanup(&convertor); OBJ_DESTRUCT(&convertor); return ret; }
/* completion of an accumulate get operation */ static void ompi_osc_rdma_acc_get_complete (struct mca_btl_base_module_t *btl, struct mca_btl_base_endpoint_t *endpoint, void *local_address, mca_btl_base_registration_handle_t *local_handle, void *context, void *data, int status) { ompi_osc_rdma_request_t *request = (ompi_osc_rdma_request_t *) context; intptr_t source = (intptr_t) local_address + request->offset; ompi_osc_rdma_sync_t *sync = request->sync; ompi_osc_rdma_module_t *module = sync->module; assert (OMPI_SUCCESS == status); if (OMPI_SUCCESS == status && OMPI_OSC_RDMA_TYPE_GET_ACC == request->type) { if (NULL == request->result_addr) { /* result buffer is not necessarily contiguous. use the opal datatype engine to * copy the data over in this case */ struct iovec iov = {.iov_base = (void *) source, request->len}; uint32_t iov_count = 1; size_t size = request->len; opal_convertor_unpack (&request->convertor, &iov, &iov_count, &size); opal_convertor_cleanup (&request->convertor); } else { /* copy contiguous data to the result buffer */ ompi_datatype_sndrcv ((void *) source, request->len, MPI_BYTE, request->result_addr, request->result_count, request->result_dt); } if (&ompi_mpi_op_no_op.op == request->op) { /* this is a no-op. nothing more to do except release resources and the accumulate lock */ ompi_osc_rdma_acc_put_complete (btl, endpoint, local_address, local_handle, context, data, status); return; } } /* accumulate the data */ if (&ompi_mpi_op_replace.op != request->op) { ompi_op_reduce (request->op, request->origin_addr, (void *) source, request->origin_count, request->origin_dt); } /* initiate the put of the accumulated data */ status = module->selected_btl->btl_put (module->selected_btl, endpoint, (void *) source, request->target_address, local_handle, (mca_btl_base_registration_handle_t *) request->ctx, request->len, 0, MCA_BTL_NO_ORDER, ompi_osc_rdma_acc_put_complete, request, NULL); /* TODO -- we can do better. probably should queue up the next step and handle it in progress */ assert (OPAL_SUCCESS == status); }
static void opal_convertor_destruct( opal_convertor_t* convertor ) { opal_convertor_cleanup( convertor ); }
int mca_common_ompio_file_read (ompio_file_t *fh, void *buf, int count, struct ompi_datatype_t *datatype, ompi_status_public_t *status) { int ret = OMPI_SUCCESS; size_t total_bytes_read = 0; /* total bytes that have been read*/ size_t bytes_per_cycle = 0; /* total read in each cycle by each process*/ int index = 0; int cycles = 0; uint32_t iov_count = 0; struct iovec *decoded_iov = NULL; size_t max_data=0, real_bytes_read=0; size_t spc=0; ssize_t ret_code=0; int i = 0; /* index into the decoded iovec of the buffer */ int j = 0; /* index into the file vie iovec */ if (fh->f_amode & MPI_MODE_WRONLY){ // opal_output(10, "Improper use of FILE Mode, Using WRONLY for Read!\n"); ret = MPI_ERR_ACCESS; return ret; } if ( 0 == count ) { if ( MPI_STATUS_IGNORE != status ) { status->_ucount = 0; } return ret; } #if OPAL_CUDA_SUPPORT int is_gpu, is_managed; opal_convertor_t convertor; mca_common_ompio_check_gpu_buf ( fh, buf, &is_gpu, &is_managed); if ( is_gpu && !is_managed ) { char *tbuf=NULL; OMPIO_CUDA_PREPARE_BUF(fh,buf,count,datatype,tbuf,&convertor,max_data,decoded_iov,iov_count); } else { mca_common_ompio_decode_datatype (fh, datatype, count, buf, &max_data, &decoded_iov, &iov_count); } #else mca_common_ompio_decode_datatype (fh, datatype, count, buf, &max_data, &decoded_iov, &iov_count); #endif if ( 0 < max_data && 0 == fh->f_iov_count ) { if ( MPI_STATUS_IGNORE != status ) { status->_ucount = 0; } return OMPI_SUCCESS; } if ( -1 == OMPIO_MCA_GET(fh, cycle_buffer_size )) { bytes_per_cycle = max_data; } else { bytes_per_cycle = OMPIO_MCA_GET(fh, cycle_buffer_size); } cycles = ceil((double)max_data/bytes_per_cycle); #if 0 printf ("Bytes per Cycle: %d Cycles: %d max_data:%d \n",bytes_per_cycle, cycles, max_data); #endif j = fh->f_index_in_file_view; for (index = 0; index < cycles; index++) { mca_common_ompio_build_io_array ( fh, index, cycles, bytes_per_cycle, max_data, iov_count, decoded_iov, &i, &j, &total_bytes_read, &spc, &fh->f_io_array, &fh->f_num_of_io_entries); if (fh->f_num_of_io_entries) { ret_code = fh->f_fbtl->fbtl_preadv (fh); if ( 0<= ret_code ) { real_bytes_read+=(size_t)ret_code; } } fh->f_num_of_io_entries = 0; if (NULL != fh->f_io_array) { free (fh->f_io_array); fh->f_io_array = NULL; } } #if OPAL_CUDA_SUPPORT if ( is_gpu && !is_managed ) { size_t pos=0; opal_convertor_unpack (&convertor, decoded_iov, &iov_count, &pos ); opal_convertor_cleanup (&convertor); mca_common_ompio_release_buf (fh, decoded_iov->iov_base); } #endif if (NULL != decoded_iov) { free (decoded_iov); decoded_iov = NULL; } if ( MPI_STATUS_IGNORE != status ) { status->_ucount = real_bytes_read; } return ret; }
/* try to get a small message out on to the wire quickly */ static inline int mca_pml_ob1_send_inline (void *buf, size_t count, ompi_datatype_t * datatype, int dst, int tag, int16_t seqn, ompi_proc_t *dst_proc, mca_bml_base_endpoint_t* endpoint, ompi_communicator_t * comm) { mca_btl_base_descriptor_t *des = NULL; mca_pml_ob1_match_hdr_t match; mca_bml_base_btl_t *bml_btl; OPAL_PTRDIFF_TYPE lb, extent; opal_convertor_t convertor; size_t size = 0; int rc; bml_btl = mca_bml_base_btl_array_get_next(&endpoint->btl_eager); ompi_datatype_get_extent (datatype, &lb, &extent); if (OPAL_UNLIKELY((extent * count) > 256 || !bml_btl->btl->btl_sendi)) { return OMPI_ERR_NOT_AVAILABLE; } if (count > 0) { /* initialize just enough of the convertor to avoid a SEGV in opal_convertor_cleanup */ OBJ_CONSTRUCT(&convertor, opal_convertor_t); /* We will create a convertor specialized for the */ /* remote architecture and prepared with the datatype. */ opal_convertor_copy_and_prepare_for_send (dst_proc->proc_convertor, (const struct opal_datatype_t *) datatype, count, buf, 0, &convertor); opal_convertor_get_packed_size (&convertor, &size); } match.hdr_common.hdr_flags = 0; match.hdr_common.hdr_type = MCA_PML_OB1_HDR_TYPE_MATCH; match.hdr_ctx = comm->c_contextid; match.hdr_src = comm->c_my_rank; match.hdr_tag = tag; match.hdr_seq = seqn; ob1_hdr_hton(&match, MCA_PML_OB1_HDR_TYPE_MATCH, dst_proc); /* try to send immediately */ rc = mca_bml_base_sendi (bml_btl, &convertor, &match, OMPI_PML_OB1_MATCH_HDR_LEN, size, MCA_BTL_NO_ORDER, MCA_BTL_DES_FLAGS_PRIORITY | MCA_BTL_DES_FLAGS_BTL_OWNERSHIP, MCA_PML_OB1_HDR_TYPE_MATCH, &des); if (count > 0) { opal_convertor_cleanup (&convertor); } if (OPAL_UNLIKELY(OMPI_SUCCESS != rc)) { if (des) { mca_bml_base_free (bml_btl, des); } return rc; } return (int) size; }
int mca_common_ompio_file_iwrite (ompio_file_t *fh, const void *buf, int count, struct ompi_datatype_t *datatype, ompi_request_t **request) { int ret = OMPI_SUCCESS; mca_ompio_request_t *ompio_req=NULL; size_t spc=0; if (fh->f_amode & MPI_MODE_RDONLY){ // opal_output(10, "Improper use of FILE Mode, Using RDONLY for write!\n"); ret = MPI_ERR_READ_ONLY; return ret; } mca_common_ompio_request_alloc ( &ompio_req, MCA_OMPIO_REQUEST_WRITE); if ( 0 == count ) { ompio_req->req_ompi.req_status.MPI_ERROR = OMPI_SUCCESS; ompio_req->req_ompi.req_status._ucount = 0; ompi_request_complete (&ompio_req->req_ompi, false); *request = (ompi_request_t *) ompio_req; return OMPI_SUCCESS; } if ( NULL != fh->f_fbtl->fbtl_ipwritev ) { /* This fbtl has support for non-blocking operations */ uint32_t iov_count = 0; struct iovec *decoded_iov = NULL; size_t max_data = 0; size_t total_bytes_written =0; int i = 0; /* index into the decoded iovec of the buffer */ int j = 0; /* index into the file vie iovec */ #if OPAL_CUDA_SUPPORT int is_gpu, is_managed; mca_common_ompio_check_gpu_buf ( fh, buf, &is_gpu, &is_managed); if ( is_gpu && !is_managed ) { size_t pos=0; char *tbuf=NULL; opal_convertor_t convertor; OMPIO_CUDA_PREPARE_BUF(fh,buf,count,datatype,tbuf,&convertor,max_data,decoded_iov,iov_count); opal_convertor_pack (&convertor, decoded_iov, &iov_count, &pos ); opal_convertor_cleanup (&convertor); ompio_req->req_tbuf = tbuf; ompio_req->req_size = max_data; } else { mca_common_ompio_decode_datatype (fh, datatype, count, buf, &max_data, &decoded_iov, &iov_count); } #else mca_common_ompio_decode_datatype (fh, datatype, count, buf, &max_data, &decoded_iov, &iov_count); #endif if ( 0 < max_data && 0 == fh->f_iov_count ) { ompio_req->req_ompi.req_status.MPI_ERROR = OMPI_SUCCESS; ompio_req->req_ompi.req_status._ucount = 0; ompi_request_complete (&ompio_req->req_ompi, false); *request = (ompi_request_t *) ompio_req; return OMPI_SUCCESS; } j = fh->f_index_in_file_view; /* Non blocking operations have to occur in a single cycle */ mca_common_ompio_build_io_array ( fh, 0, // index of current cycle iteration 1, // number of cycles max_data, // setting bytes_per_cycle to max_data max_data, iov_count, decoded_iov, &i, &j, &total_bytes_written, &spc); if (fh->f_num_of_io_entries) { fh->f_fbtl->fbtl_ipwritev (fh, (ompi_request_t *) ompio_req); } mca_common_ompio_register_progress (); fh->f_num_of_io_entries = 0; if (NULL != fh->f_io_array) { free (fh->f_io_array); fh->f_io_array = NULL; } if (NULL != decoded_iov) { free (decoded_iov); decoded_iov = NULL; } } else { // This fbtl does not support non-blocking write operations ompi_status_public_t status; ret = mca_common_ompio_file_write(fh,buf,count,datatype, &status); ompio_req->req_ompi.req_status.MPI_ERROR = ret; ompio_req->req_ompi.req_status._ucount = status._ucount; ompi_request_complete (&ompio_req->req_ompi, false); } *request = (ompi_request_t *) ompio_req; return ret; }
static inline int ompi_osc_rdma_gacc_master (ompi_osc_rdma_sync_t *sync, const void *source_buffer, int source_count, ompi_datatype_t *source_datatype, void *result_buffer, int result_count, ompi_datatype_t *result_datatype, ompi_osc_rdma_peer_t *peer, uint64_t target_address, mca_btl_base_registration_handle_t *target_handle, int target_count, ompi_datatype_t *target_datatype, ompi_op_t *op, ompi_osc_rdma_request_t *request) { ompi_osc_rdma_module_t *module = sync->module; struct iovec source_iovec[OMPI_OSC_RDMA_DECODE_MAX], target_iovec[OMPI_OSC_RDMA_DECODE_MAX]; const size_t acc_limit = (mca_osc_rdma_component.buffer_size >> 3); uint32_t source_primitive_count, target_primitive_count; opal_convertor_t source_convertor, target_convertor; uint32_t source_iov_count, target_iov_count; uint32_t source_iov_index, target_iov_index; ompi_datatype_t *source_primitive, *target_primitive; /* needed for opal_convertor_raw but not used */ size_t source_size, target_size; ompi_osc_rdma_request_t *subreq; size_t result_position; ptrdiff_t lb, extent; int ret, acc_len; bool done; (void) ompi_datatype_get_extent (target_datatype, &lb, &extent); target_address += lb; /* fast path for accumulate on built-in types */ if (OPAL_LIKELY((!source_count || ompi_datatype_is_predefined (source_datatype)) && ompi_datatype_is_predefined (target_datatype) && (!result_count || ompi_datatype_is_predefined (result_datatype)) && (target_datatype->super.size * target_count <= acc_limit))) { if (NULL == request) { OMPI_OSC_RDMA_REQUEST_ALLOC(module, peer, request); request->internal = true; request->type = result_datatype ? OMPI_OSC_RDMA_TYPE_GET_ACC : OMPI_OSC_RDMA_TYPE_ACC; } if (source_datatype) { (void) ompi_datatype_get_extent (source_datatype, &lb, &extent); source_buffer = (void *)((intptr_t) source_buffer + lb); } if (result_datatype) { (void) ompi_datatype_get_extent (result_datatype, &lb, &extent); result_buffer = (void *)((intptr_t) result_buffer + lb); } ret = ompi_osc_rdma_gacc_contig (sync, source_buffer, source_count, source_datatype, result_buffer, result_count, result_datatype, peer, target_address, target_handle, target_count, target_datatype, op, request); if (OPAL_LIKELY(OMPI_SUCCESS == ret)) { return OMPI_SUCCESS; } if (source_datatype) { /* the convertors will handle the lb */ (void) ompi_datatype_get_extent (source_datatype, &lb, &extent); source_buffer = (void *)((intptr_t) source_buffer - lb); } if (result_datatype) { (void) ompi_datatype_get_extent (result_datatype, &lb, &extent); result_buffer = (void *)((intptr_t) result_buffer - lb); } } /* the convertor will handle lb from here */ (void) ompi_datatype_get_extent (target_datatype, &lb, &extent); target_address -= lb; /* get the primitive datatype info */ ret = ompi_osc_base_get_primitive_type_info (target_datatype, &target_primitive, &target_primitive_count); if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) { /* target datatype is not made up of a single basic datatype */ return ret; } if (source_datatype) { ret = ompi_osc_base_get_primitive_type_info (source_datatype, &source_primitive, &source_primitive_count); if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) { /* target datatype is not made up of a single basic datatype */ return ret; } if (OPAL_UNLIKELY(source_primitive != target_primitive)) { return MPI_ERR_TYPE; } } /* prepare convertors for the source and target. these convertors will be used to determine the * contiguous segments within the source and target. */ /* the source may be NULL if using MPI_OP_NO_OP with MPI_Get_accumulate */ if (source_datatype) { OBJ_CONSTRUCT(&source_convertor, opal_convertor_t); ret = opal_convertor_copy_and_prepare_for_send (ompi_mpi_local_convertor, &source_datatype->super, source_count, source_buffer, 0, &source_convertor); if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) { return ret; } } /* target_datatype can never be NULL */ OBJ_CONSTRUCT(&target_convertor, opal_convertor_t); ret = opal_convertor_copy_and_prepare_for_send (ompi_mpi_local_convertor, &target_datatype->super, target_count, (void *) (intptr_t) target_address, 0, &target_convertor); if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) { return ret; } if (request) { /* keep the request from completing until all the transfers have started */ request->outstanding_requests = 1; } target_iov_index = 0; target_iov_count = 0; result_position = 0; do { /* decode segments of the source data */ source_iov_count = OMPI_OSC_RDMA_DECODE_MAX; source_iov_index = 0; /* opal_convertor_raw returns done when it has reached the end of the data */ if (!source_datatype) { done = true; source_iovec[0].iov_len = (size_t) -1; source_iovec[0].iov_base = NULL; source_iov_count = 1; } else { done = opal_convertor_raw (&source_convertor, source_iovec, &source_iov_count, &source_size); } /* loop on the target segments until we have exhaused the decoded source data */ while (source_iov_index != source_iov_count) { if (target_iov_index == target_iov_count) { /* decode segments of the target buffer */ target_iov_count = OMPI_OSC_RDMA_DECODE_MAX; target_iov_index = 0; (void) opal_convertor_raw (&target_convertor, target_iovec, &target_iov_count, &target_size); } /* we already checked that the target was large enough. this should be impossible */ assert (0 != target_iov_count); /* determine how much to put in this operation */ acc_len = min(target_iovec[target_iov_index].iov_len, source_iovec[source_iov_index].iov_len); acc_len = min((size_t) acc_len, acc_limit); /* execute the get */ OMPI_OSC_RDMA_REQUEST_ALLOC(module, peer, subreq); subreq->internal = true; subreq->parent_request = request; if (request) { (void) OPAL_THREAD_ADD32 (&request->outstanding_requests, 1); } if (result_datatype) { /* prepare a convertor for this part of the result */ opal_convertor_copy_and_prepare_for_recv (ompi_mpi_local_convertor, &result_datatype->super, result_count, result_buffer, 0, &subreq->convertor); opal_convertor_set_position (&subreq->convertor, &result_position); subreq->type = OMPI_OSC_RDMA_TYPE_GET_ACC; } else { subreq->type = OMPI_OSC_RDMA_TYPE_ACC; } OPAL_OUTPUT_VERBOSE((60, ompi_osc_base_framework.framework_output, "target index = %d, target = {%p, %lu}, source_index = %d, source = {%p, %lu}, result = %p, result position = %lu, " "acc_len = %d, count = %lu", target_iov_index, target_iovec[target_iov_index].iov_base, (unsigned long) target_iovec[target_iov_index].iov_len, source_iov_index, source_iovec[source_iov_index].iov_base, (unsigned long) source_iovec[source_iov_index].iov_len, result_buffer, (unsigned long) result_position, acc_len, (unsigned long)(acc_len / target_primitive->super.size))); ret = ompi_osc_rdma_gacc_contig (sync, source_iovec[source_iov_index].iov_base, acc_len / target_primitive->super.size, target_primitive, NULL, 0, NULL, peer, (uint64_t) (intptr_t) target_iovec[target_iov_index].iov_base, target_handle, acc_len / target_primitive->super.size, target_primitive, op, subreq); if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) { if (OPAL_UNLIKELY(OMPI_ERR_OUT_OF_RESOURCE != ret)) { /* something bad happened. need to figure out how to handle these errors */ return ret; } /* progress and try again */ ompi_osc_rdma_progress (module); continue; } /* adjust io vectors */ target_iovec[target_iov_index].iov_len -= acc_len; source_iovec[source_iov_index].iov_len -= acc_len; target_iovec[target_iov_index].iov_base = (void *)((intptr_t) target_iovec[target_iov_index].iov_base + acc_len); source_iovec[source_iov_index].iov_base = (void *)((intptr_t) source_iovec[source_iov_index].iov_base + acc_len); result_position += acc_len; source_iov_index += !source_datatype || (0 == source_iovec[source_iov_index].iov_len); target_iov_index += (0 == target_iovec[target_iov_index].iov_len); } } while (!done); if (request) { /* release our reference so the request can complete */ (void) OPAL_THREAD_ADD32 (&request->outstanding_requests, -1); } if (source_datatype) { opal_convertor_cleanup (&source_convertor); OBJ_DESTRUCT(&source_convertor); } opal_convertor_cleanup (&target_convertor); OBJ_DESTRUCT(&target_convertor); return OMPI_SUCCESS; }