int mca_spml_ikrit_put(shmem_ctx_t ctx, void* dst_addr, size_t size, void* src_addr, int dst) { int err; mca_spml_ikrit_put_request_t *put_req; mxm_wait_t wait; put_req = 0; err = mca_spml_ikrit_put_internal(dst_addr, size, src_addr, dst, (void **) &put_req, 0); if (OSHMEM_SUCCESS != err) { SPML_ERROR("put failed - aborting"); oshmem_shmem_abort(-1); return OSHMEM_ERROR; } if (!put_req) return OSHMEM_SUCCESS; wait.req = &put_req->mxm_req.base; wait.state = (mxm_req_state_t)(MXM_REQ_SENT | MXM_REQ_COMPLETED); wait.progress_cb = NULL; wait.progress_arg = NULL; mxm_wait(&wait); return OSHMEM_SUCCESS; }
int ompi_mtl_mxm_send(struct mca_mtl_base_module_t* mtl, struct ompi_communicator_t* comm, int dest, int tag, struct opal_convertor_t *convertor, mca_pml_base_send_mode_t mode) { mxm_send_req_t mxm_send_req; mxm_wait_t wait; mxm_error_t err; int ret; /* prepare local send request */ mxm_send_req.base.state = MXM_REQ_NEW; mxm_send_req.base.mq = ompi_mtl_mxm_mq_lookup(comm); mxm_send_req.base.conn = ompi_mtl_mxm_conn_lookup(comm, dest); mxm_send_req.base.flags = MXM_REQ_FLAG_BLOCKING; mxm_send_req.base.context = NULL; ret = ompi_mtl_mxm_choose_send_datatype(&mxm_send_req, convertor); if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) { return ret; } mxm_send_req.base.data.buffer.mkey = MXM_MKEY_NONE; mxm_send_req.base.completed_cb = NULL; if (mode == MCA_PML_BASE_SEND_SYNCHRONOUS) { mxm_send_req.base.flags |= MXM_REQ_FLAG_SEND_SYNC; } mxm_send_req.opcode = MXM_REQ_OP_SEND; mxm_send_req.op.send.tag = tag; mxm_send_req.op.send.imm_data = ompi_comm_rank(comm); /* post-send */ err = mxm_req_send(&mxm_send_req); if (MXM_OK != err) { orte_show_help("help-mtl-mxm.txt", "error posting send", true, 0, mxm_error_string(err)); return OMPI_ERROR; } /* wait for request completion */ wait.req = &mxm_send_req.base; wait.state = MXM_REQ_COMPLETED; wait.progress_cb = ompi_mtl_mxm_send_progress_cb; wait.progress_arg = NULL; mxm_wait(&wait); return OMPI_SUCCESS; }
static inline void gasnetc_ReqRepWait(mxm_send_req_t * mxm_sreq, uint8_t is_request, uint8_t msg_num) { if (is_request) { /* * Ensure progress, but only on requester side (even on async request). * We don't want to have recursion on responder side - otherwise * send might be called from context of receive and so on. */ #if GASNET_DEBUG_AM MXM_LOG("[pid %d] polling and testing(%s, msg_num = 0x%02x)...\n", getpid(), is_request ? "request" : "response", msg_num); #endif while (!mxm_req_test(&mxm_sreq->base)) gasnetc_AMPoll(); #if GASNET_DEBUG_AM MXM_LOG("[pid %d] done polling and testing(%s, msg_num = 0x%02x)...\n", getpid(), is_request ? "request" : "response", msg_num); #endif } else { mxm_wait_t wait; wait.progress_cb = NULL; wait.progress_arg = NULL; wait.req = &mxm_sreq->base; wait.state = MXM_REQ_COMPLETED; /* * We're on the responder side - just wait for completion. */ #if GASNET_DEBUG_AM MXM_LOG("[pid %d] calling mxm_req_wait(%s, msg_num = 0x%02x)...\n", getpid(), is_request ? "request" : "response", msg_num); #endif mxm_wait(&wait); #if GASNET_DEBUG_AM MXM_LOG("[pid %d] mxm_req_wait(%s, msg_num = 0x%02x) returned\n", getpid(), is_request ? "request" : "response", msg_num); #endif } }
/* simple buffered put implementation. NOT IN USE * Problems: * - slighly worse performance than impl based on non buffered put * - fence complexity is O(n_active_connections) instead of O(n_connections_with_outstanding_puts). * Later is bounded by the network RTT & mxm ack timer. */ int mca_spml_ikrit_put_simple(void* dst_addr, size_t size, void* src_addr, int dst) { void *rva; mxm_send_req_t mxm_req; mxm_wait_t wait; int ptl_id; mxm_mem_key_t *mkey; static int count; ptl_id = get_ptl_id(dst); mkey = mca_spml_ikrit_get_mkey(dst, dst_addr, ptl_id, &rva, &mca_spml_ikrit); SPML_VERBOSE_FASTPATH(100, "put: pe:%d ptl=%d dst=%p <- src: %p sz=%d. dst_rva=%p, %s", dst, ptl_id, dst_addr, src_addr, (int)size, (void *)rva); if (NULL == mkey) { memcpy((void *) (unsigned long) rva, src_addr, size); /* call progress as often as we would have with regular put */ if (++count % SPML_IKRIT_PACKETS_PER_SYNC == 0) mxm_progress(mca_spml_ikrit.mxm_context); return OSHMEM_SUCCESS; } SPML_VERBOSE_FASTPATH(100, "put: pe:%d ptl=%d dst=%p <- src: %p sz=%d. dst_rva=%p, %s", dst, MXM_PTL_RDMA, dst_addr, src_addr, (int)size, (void *)rva); /* fill out request */ mxm_req.base.mq = mca_spml_ikrit.mxm_mq; mxm_req.flags = MXM_REQ_SEND_FLAG_BLOCKING; mxm_req.base.conn = mca_spml_ikrit.mxm_peers[dst].mxm_conn; mxm_req.base.data_type = MXM_REQ_DATA_BUFFER; mxm_req.base.data.buffer.ptr = src_addr; mxm_req.base.data.buffer.length = size; mxm_req.base.completed_cb = 0; mxm_req.base.context = 0; mxm_req.opcode = MXM_REQ_OP_PUT; mxm_req.op.mem.remote_vaddr = (intptr_t) rva; mxm_req.base.state = MXM_REQ_NEW; mxm_req.base.error = MXM_OK; mxm_req.op.mem.remote_mkey = mkey; if (mca_spml_ikrit.mxm_peers[dst].need_fence == 0) { opal_list_append(&mca_spml_ikrit.active_peers, &mca_spml_ikrit.mxm_peers[dst].link); mca_spml_ikrit.mxm_peers[dst].need_fence = 1; } SPML_IKRIT_MXM_POST_SEND(mxm_req); wait.req = &mxm_req.base; wait.state = (mxm_req_state_t)(MXM_REQ_SENT | MXM_REQ_COMPLETED); wait.progress_cb = NULL; wait.progress_arg = NULL; mxm_wait(&wait); return OSHMEM_SUCCESS; }
/* simple buffered put implementation. NOT IN USE * Problems: * - slighly worse performance than impl based on non buffered put * - fence complexity is O(n_active_connections) instead of O(n_connections_with_outstanding_puts). * Later is bounded by the network RTT & mxm ack timer. */ int mca_spml_ikrit_put_simple(void* dst_addr, size_t size, void* src_addr, int dst) { void *rva; mxm_send_req_t mxm_req; mxm_wait_t wait; int ptl_id; sshmem_mkey_t *r_mkey; static int count; ptl_id = get_ptl_id(dst); /* Get rkey of remote PE (dst proc) which must be on memheap */ r_mkey = mca_memheap_base_get_cached_mkey(dst, dst_addr, ptl_id, &rva); if (!r_mkey) { SPML_ERROR("pe=%d: %p is not address of shared variable", dst, dst_addr); oshmem_shmem_abort(-1); return OSHMEM_ERROR; } #if SPML_IKRIT_PUT_DEBUG == 1 SPML_VERBOSE(100, "put: pe:%d ptl=%d dst=%p <- src: %p sz=%d. dst_rva=%p, %s", dst, ptl_id, dst_addr, src_addr, (int)size, (void *)rva, mca_spml_base_mkey2str(r_mkey)); #endif if (ptl_id == MXM_PTL_SHM) { if (mca_memheap_base_can_local_copy(r_mkey, dst_addr)) { memcpy((void *) (unsigned long) rva, src_addr, size); /* call progress as often as we would have with regular put */ if (++count % SPML_IKRIT_PACKETS_PER_SYNC == 0) mxm_progress(mca_spml_ikrit.mxm_context); return OSHMEM_SUCCESS; } /* segment not mapped - fallback to rmda */ ptl_id = MXM_PTL_RDMA; r_mkey = mca_memheap_base_get_cached_mkey(dst, //(unsigned long) dst_addr, dst_addr, ptl_id, &rva); if (!r_mkey) { SPML_ERROR("pe=%d: %p is not address of shared variable", dst, dst_addr); oshmem_shmem_abort(-1); return OSHMEM_ERROR; } } #if SPML_IKRIT_PUT_DEBUG == 1 SPML_VERBOSE(100, "put: pe:%d ptl=%d dst=%p <- src: %p sz=%d. dst_rva=%p, %s", dst, ptl_id, dst_addr, src_addr, (int)size, (void *)rva, mca_spml_base_mkey2str(r_mkey)); #endif /* fill out request */ mxm_req.base.mq = mca_spml_ikrit.mxm_mq; #if MXM_API < MXM_VERSION(2,0) mxm_req.base.flags = MXM_REQ_FLAG_BLOCKING; #else mxm_req.flags = MXM_REQ_SEND_FLAG_BLOCKING; #endif mxm_req.base.conn = mca_spml_ikrit.mxm_peers[dst]->mxm_conn; mxm_req.base.data_type = MXM_REQ_DATA_BUFFER; mxm_req.base.data.buffer.ptr = src_addr; mxm_req.base.data.buffer.length = size; mxm_req.base.completed_cb = 0; mxm_req.base.context = 0; mxm_req.opcode = MXM_REQ_OP_PUT; mxm_req.op.mem.remote_vaddr = (intptr_t) rva; mxm_req.base.state = MXM_REQ_NEW; mxm_req.base.error = MXM_OK; #if MXM_API < MXM_VERSION(2, 0) mxm_req.base.data.buffer.memh = NULL; mxm_req.op.mem.remote_memh = NULL; #else mxm_req.op.mem.remote_mkey = to_mxm_mkey(r_mkey); #endif if (mca_spml_ikrit.mxm_peers[dst]->need_fence == 0) { opal_list_append(&mca_spml_ikrit.active_peers, &mca_spml_ikrit.mxm_peers[dst]->super); mca_spml_ikrit.mxm_peers[dst]->need_fence = 1; } SPML_IKRIT_MXM_POST_SEND(mxm_req); wait.req = &mxm_req.base; wait.state = (mxm_req_state_t)(MXM_REQ_SENT | MXM_REQ_COMPLETED); wait.progress_cb = NULL; wait.progress_arg = NULL; mxm_wait(&wait); return OSHMEM_SUCCESS; }