2014-02-25 21:36:43 +04:00
|
|
|
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
|
2006-07-18 02:08:55 +04:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
|
|
|
* All rights reserved.
|
|
|
|
* Copyright (c) 2004-2005 The Trustees of the University of Tennessee.
|
|
|
|
* All rights reserved.
|
2014-02-25 21:36:43 +04:00
|
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
2006-07-18 02:08:55 +04:00
|
|
|
* University of Stuttgart. All rights reserved.
|
|
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
|
|
* All rights reserved.
|
2014-02-25 21:36:43 +04:00
|
|
|
* Copyright (c) 2007-2014 Los Alamos National Security, LLC. All rights
|
|
|
|
* reserved.
|
2010-07-20 22:45:48 +04:00
|
|
|
* Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
|
2014-02-25 21:36:43 +04:00
|
|
|
* Copyright (c) 2012-2013 Sandia National Laboratories. All rights reserved.
|
2006-07-18 02:08:55 +04:00
|
|
|
* $COPYRIGHT$
|
2014-02-25 21:36:43 +04:00
|
|
|
*
|
2006-07-18 02:08:55 +04:00
|
|
|
* Additional copyrights may follow
|
2014-02-25 21:36:43 +04:00
|
|
|
*
|
2006-07-18 02:08:55 +04:00
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ompi_config.h"
|
|
|
|
#include "mpi.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2014-02-25 21:36:43 +04:00
|
|
|
#include <string.h>
|
2006-07-18 02:08:55 +04:00
|
|
|
|
|
|
|
#include "osc_rdma.h"
|
2014-02-25 21:36:43 +04:00
|
|
|
#include "osc_rdma_request.h"
|
2006-07-18 02:08:55 +04:00
|
|
|
#include "osc_rdma_header.h"
|
2014-02-25 21:36:43 +04:00
|
|
|
#include "osc_rdma_frag.h"
|
2006-07-18 02:08:55 +04:00
|
|
|
#include "osc_rdma_data_move.h"
|
2014-02-25 21:36:43 +04:00
|
|
|
|
|
|
|
#include "opal_stdint.h"
|
2008-05-05 17:57:27 +04:00
|
|
|
#include "ompi/memchecker.h"
|
2014-02-25 21:36:43 +04:00
|
|
|
#include "ompi/mca/pml/pml.h"
|
2009-01-14 23:15:15 +03:00
|
|
|
#include "ompi/mca/osc/base/osc_base_obj_convert.h"
|
2014-02-25 21:36:43 +04:00
|
|
|
#include "ompi/mca/osc/base/base.h"
|
2006-07-18 02:08:55 +04:00
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
/* progress an OSC request */
|
|
|
|
static int ompi_osc_rdma_req_comm_complete (ompi_request_t *request)
|
2006-07-18 02:08:55 +04:00
|
|
|
{
|
2014-02-25 21:36:43 +04:00
|
|
|
ompi_osc_rdma_request_t *rdma_request = (ompi_osc_rdma_request_t *) request->req_complete_cb_data;
|
|
|
|
ompi_osc_rdma_module_t *module = rdma_request->module;
|
|
|
|
|
|
|
|
OPAL_OUTPUT_VERBOSE((10, ompi_osc_base_framework.framework_output,
|
|
|
|
"ompi_osc_rdma_req_comm_complete called tag = %d",
|
|
|
|
request->req_status.MPI_TAG));
|
|
|
|
|
|
|
|
mark_outgoing_completion (module);
|
|
|
|
|
|
|
|
OPAL_THREAD_LOCK(&ompi_request_lock);
|
|
|
|
if (0 == --rdma_request->outstanding_requests) {
|
|
|
|
ompi_osc_rdma_request_complete (rdma_request, request->req_status.MPI_ERROR);
|
|
|
|
}
|
|
|
|
OPAL_THREAD_UNLOCK(&ompi_request_lock);
|
|
|
|
|
|
|
|
/* put this request on the garbage colletion list */
|
|
|
|
OPAL_THREAD_LOCK(&module->lock);
|
|
|
|
opal_list_append (&module->request_gc, (opal_list_item_t *) request);
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
2006-07-18 02:08:55 +04:00
|
|
|
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
/* self communication optimizations */
|
|
|
|
static inline int ompi_osc_rdma_put_self (void *source, int source_count, ompi_datatype_t *source_datatype,
|
|
|
|
OPAL_PTRDIFF_TYPE target_disp, int target_count, ompi_datatype_t *target_datatype,
|
|
|
|
ompi_osc_rdma_module_t *module, ompi_osc_rdma_request_t *request)
|
|
|
|
{
|
|
|
|
void *target = (unsigned char*) module->baseptr +
|
|
|
|
((unsigned long) target_disp * module->disp_unit);
|
|
|
|
int ret;
|
2006-07-18 02:08:55 +04:00
|
|
|
|
2014-03-12 03:01:42 +04:00
|
|
|
if (!(module->passive_target_access_epoch || module->active_eager_send_active)) {
|
2014-03-12 03:45:23 +04:00
|
|
|
return OMPI_ERR_RMA_SYNC;
|
2014-03-12 03:01:42 +04:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
ret = ompi_datatype_sndrcv (source, source_count, source_datatype,
|
|
|
|
target, target_count, target_datatype);
|
|
|
|
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (request) {
|
|
|
|
ompi_osc_rdma_request_complete (request, MPI_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int ompi_osc_rdma_get_self (void *target, int target_count, ompi_datatype_t *target_datatype,
|
|
|
|
OPAL_PTRDIFF_TYPE source_disp, int source_count, ompi_datatype_t *source_datatype,
|
|
|
|
ompi_osc_rdma_module_t *module, ompi_osc_rdma_request_t *request)
|
2006-07-18 02:08:55 +04:00
|
|
|
{
|
2014-02-25 21:36:43 +04:00
|
|
|
void *source = (unsigned char*) module->baseptr +
|
|
|
|
((unsigned long) source_disp * module->disp_unit);
|
2006-07-18 02:08:55 +04:00
|
|
|
int ret;
|
|
|
|
|
2014-03-12 03:01:42 +04:00
|
|
|
if (!(module->passive_target_access_epoch || module->active_eager_send_active)) {
|
2014-03-12 03:45:23 +04:00
|
|
|
return OMPI_ERR_RMA_SYNC;
|
2014-03-12 03:01:42 +04:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
ret = ompi_datatype_sndrcv (source, source_count, source_datatype,
|
|
|
|
target, target_count, target_datatype);
|
|
|
|
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
|
|
|
|
return ret;
|
2006-09-22 00:49:15 +04:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
if (request) {
|
|
|
|
ompi_osc_rdma_request_complete (request, MPI_SUCCESS);
|
2006-07-18 02:08:55 +04:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int ompi_osc_rdma_cas_self (void *source, void *compare, void *result, ompi_datatype_t *datatype,
|
|
|
|
OPAL_PTRDIFF_TYPE target_disp, ompi_osc_rdma_module_t *module)
|
|
|
|
{
|
|
|
|
void *target = (unsigned char*) module->baseptr +
|
|
|
|
((unsigned long) target_disp * module->disp_unit);
|
|
|
|
|
2014-03-12 03:01:42 +04:00
|
|
|
if (!(module->passive_target_access_epoch || module->active_eager_send_active)) {
|
2014-03-12 03:45:23 +04:00
|
|
|
return OMPI_ERR_RMA_SYNC;
|
2014-03-12 03:01:42 +04:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
ompi_osc_rdma_accumulate_lock (module);
|
|
|
|
|
|
|
|
memcpy (result, target, datatype->super.size);
|
|
|
|
|
|
|
|
if (0 == memcmp (compare, target, datatype->super.size)) {
|
|
|
|
memcpy (target, source, datatype->super.size);
|
|
|
|
}
|
|
|
|
|
|
|
|
ompi_osc_rdma_accumulate_unlock (module);
|
|
|
|
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int ompi_osc_rdma_acc_self (void *source, int source_count, ompi_datatype_t *source_datatype,
|
|
|
|
OPAL_PTRDIFF_TYPE target_disp, int target_count, ompi_datatype_t *target_datatype,
|
|
|
|
ompi_op_t *op, ompi_osc_rdma_module_t *module, ompi_osc_rdma_request_t *request)
|
|
|
|
{
|
|
|
|
void *target = (unsigned char*) module->baseptr +
|
|
|
|
((unsigned long) target_disp * module->disp_unit);
|
|
|
|
int ret;
|
|
|
|
|
2014-03-12 03:01:42 +04:00
|
|
|
if (!(module->passive_target_access_epoch || module->active_eager_send_active)) {
|
2014-03-12 03:45:23 +04:00
|
|
|
return OMPI_ERR_RMA_SYNC;
|
2014-03-12 03:01:42 +04:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
ompi_osc_rdma_accumulate_lock (module);
|
|
|
|
|
|
|
|
if (&ompi_mpi_op_replace.op != op) {
|
|
|
|
ret = ompi_osc_base_sndrcv_op (source, source_count, source_datatype, target, target_count, target_datatype, op);
|
|
|
|
} else {
|
|
|
|
ret = ompi_datatype_sndrcv (source, source_count, source_datatype, target, target_count, target_datatype);
|
|
|
|
}
|
|
|
|
|
|
|
|
ompi_osc_rdma_accumulate_unlock (module);
|
|
|
|
|
|
|
|
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
|
|
|
|
OPAL_OUTPUT_VERBOSE((5, ompi_osc_base_framework.framework_output,
|
|
|
|
"ompi_osc_rdma_acc_self: failed performing accumulate operation. ret = %d", ret));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (request) {
|
|
|
|
ompi_osc_rdma_request_complete (request, MPI_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int ompi_osc_rdma_gacc_self (void *source, int source_count, ompi_datatype_t *source_datatype,
|
|
|
|
void *result, int result_count, ompi_datatype_t *result_datatype,
|
|
|
|
OPAL_PTRDIFF_TYPE target_disp, int target_count, ompi_datatype_t *target_datatype,
|
|
|
|
ompi_op_t *op, ompi_osc_rdma_module_t *module, ompi_osc_rdma_request_t *request)
|
|
|
|
{
|
|
|
|
void *target = (unsigned char*) module->baseptr +
|
|
|
|
((unsigned long) target_disp * module->disp_unit);
|
|
|
|
int ret;
|
|
|
|
|
2014-03-12 03:01:42 +04:00
|
|
|
if (!(module->passive_target_access_epoch || module->active_eager_send_active)) {
|
2014-03-12 03:45:23 +04:00
|
|
|
return OMPI_ERR_RMA_SYNC;
|
2014-03-12 03:01:42 +04:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
ompi_osc_rdma_accumulate_lock (module);
|
|
|
|
|
|
|
|
do {
|
|
|
|
ret = ompi_datatype_sndrcv (target, target_count, target_datatype,
|
|
|
|
result, result_count, result_datatype);
|
|
|
|
|
|
|
|
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
|
|
|
|
OPAL_OUTPUT_VERBOSE((5, ompi_osc_base_framework.framework_output,
|
|
|
|
"ompi_osc_rdma_gacc_self: failed copying to the target buffer. ret = %d", ret));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (&ompi_mpi_op_no_op.op != op) {
|
|
|
|
if (&ompi_mpi_op_replace.op != op) {
|
|
|
|
ret = ompi_osc_base_sndrcv_op (source, source_count, source_datatype, target, target_count, target_datatype, op);
|
|
|
|
} else {
|
|
|
|
ret = ompi_datatype_sndrcv (source, source_count, source_datatype, target, target_count, target_datatype);
|
2009-01-14 23:15:15 +03:00
|
|
|
}
|
2014-02-25 21:36:43 +04:00
|
|
|
}
|
2009-01-14 23:15:15 +03:00
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
|
|
|
|
OPAL_OUTPUT_VERBOSE((5, ompi_osc_base_framework.framework_output,
|
|
|
|
"ompi_osc_rdma_gacc_self: failed performing accumulate operation. ret = %d", ret));
|
|
|
|
break;
|
2009-01-14 23:15:15 +03:00
|
|
|
}
|
2014-02-25 21:36:43 +04:00
|
|
|
} while (0);
|
2009-01-14 23:15:15 +03:00
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
ompi_osc_rdma_accumulate_unlock (module);
|
|
|
|
|
|
|
|
if (request) {
|
|
|
|
/* NTH: is it ok to use an ompi error code here? */
|
|
|
|
ompi_osc_rdma_request_complete (request, ret);
|
|
|
|
}
|
2007-05-30 21:06:19 +04:00
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
/* end: self communication optimizations */
|
2007-05-30 21:06:19 +04:00
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
static inline int ompi_osc_rdma_put_w_req (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,
|
|
|
|
ompi_win_t *win, ompi_osc_rdma_request_t *request)
|
|
|
|
{
|
|
|
|
ompi_osc_rdma_module_t *module = GET_MODULE(win);
|
|
|
|
ompi_proc_t *proc = ompi_comm_peer_lookup(module->comm, target);
|
|
|
|
ompi_osc_rdma_frag_t *frag;
|
|
|
|
ompi_osc_rdma_header_put_t *header;
|
|
|
|
size_t ddt_len, payload_len, frag_len;
|
|
|
|
bool is_long_msg = false;
|
|
|
|
const void *packed_ddt;
|
|
|
|
int tag, ret;
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
|
|
|
|
"put: 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));
|
|
|
|
|
|
|
|
/* short-circuit case */
|
|
|
|
if (0 == origin_count || 0 == target_count) {
|
|
|
|
if (request) {
|
|
|
|
ompi_osc_rdma_request_complete (request, MPI_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* optimize self communication. TODO: optimize local communication */
|
|
|
|
if (ompi_comm_rank (module->comm) == target) {
|
|
|
|
return ompi_osc_rdma_put_self (origin_addr, origin_count, origin_dt,
|
|
|
|
target_disp, target_count, target_dt,
|
|
|
|
module, request);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Compute datatype and payload lengths. Note that the datatype description
|
|
|
|
* must fit in a single buffer */
|
|
|
|
ddt_len = ompi_datatype_pack_description_length(target_dt);
|
|
|
|
payload_len = origin_dt->super.size * origin_count;
|
|
|
|
frag_len = sizeof(ompi_osc_rdma_header_put_t) + ddt_len + payload_len;
|
|
|
|
|
|
|
|
OPAL_THREAD_LOCK(&module->lock);
|
|
|
|
|
|
|
|
ret = ompi_osc_rdma_frag_alloc(module, target, frag_len, &frag, &ptr);
|
|
|
|
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
|
|
|
|
frag_len = sizeof(ompi_osc_rdma_header_put_t) + ddt_len;
|
|
|
|
ret = ompi_osc_rdma_frag_alloc(module, target, frag_len, &frag, &ptr);
|
|
|
|
if (OMPI_SUCCESS != ret) {
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
is_long_msg = true;
|
|
|
|
tag = get_tag(module);
|
|
|
|
}
|
|
|
|
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
|
|
|
|
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
|
|
|
|
"osc rdma: put long protocol: %d", (int) is_long_msg));
|
|
|
|
|
|
|
|
header = (ompi_osc_rdma_header_put_t *) ptr;
|
|
|
|
header->base.flags = 0;
|
|
|
|
header->len = frag_len;
|
|
|
|
header->count = target_count;
|
|
|
|
header->displacement = target_disp;
|
|
|
|
ptr += sizeof(ompi_osc_rdma_header_put_t);
|
|
|
|
|
|
|
|
ret = ompi_datatype_get_pack_description(target_dt, &packed_ddt);
|
|
|
|
memcpy((unsigned char*) ptr, packed_ddt, ddt_len);
|
|
|
|
ptr += ddt_len;
|
|
|
|
|
|
|
|
if (!is_long_msg) {
|
|
|
|
header->base.type = OMPI_OSC_RDMA_HDR_TYPE_PUT;
|
|
|
|
|
|
|
|
osc_rdma_copy_for_send (ptr, payload_len, origin_addr, proc, origin_count,
|
|
|
|
origin_dt);
|
|
|
|
|
|
|
|
/* the user's buffer is no longer needed so mark the request as
|
|
|
|
* complete. */
|
|
|
|
if (request) {
|
|
|
|
ompi_osc_rdma_request_complete (request, MPI_SUCCESS);
|
2007-05-30 21:06:19 +04:00
|
|
|
}
|
|
|
|
} else {
|
2014-02-25 21:36:43 +04:00
|
|
|
header->base.type = OMPI_OSC_RDMA_HDR_TYPE_PUT_LONG;
|
|
|
|
|
|
|
|
header->tag = tag;
|
|
|
|
|
|
|
|
/* increase the outgoing signal count */
|
|
|
|
ompi_osc_signal_outgoing (module, target, 1);
|
|
|
|
|
|
|
|
if (request) {
|
|
|
|
request->outstanding_requests = 1;
|
|
|
|
ret = ompi_osc_rdma_isend_w_cb (origin_addr, origin_count, origin_dt,
|
|
|
|
target, tag, module->comm, ompi_osc_rdma_req_comm_complete,
|
|
|
|
request);
|
|
|
|
} else {
|
|
|
|
ret = ompi_osc_rdma_component_isend (module,origin_addr, origin_count, origin_dt, target, tag,
|
|
|
|
module->comm);
|
|
|
|
}
|
|
|
|
if (OMPI_SUCCESS != ret) goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (OPAL_LIKELY(OMPI_SUCCESS == ret)) {
|
|
|
|
header->base.flags |= OMPI_OSC_RDMA_HDR_FLAG_VALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
OPAL_THREAD_LOCK(&module->lock);
|
|
|
|
|
|
|
|
ret = ompi_osc_rdma_frag_finish(module, frag);
|
|
|
|
|
|
|
|
if (request) {
|
|
|
|
/* need to flush now in case the caller decides to wait on the request */
|
|
|
|
ompi_osc_rdma_frag_flush_target (module, target);
|
2007-05-30 21:06:19 +04:00
|
|
|
}
|
2014-02-25 21:36:43 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
2006-07-18 02:08:55 +04:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-02-25 21:36:43 +04:00
|
|
|
ompi_osc_rdma_put(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, ompi_win_t *win)
|
|
|
|
{
|
|
|
|
return ompi_osc_rdma_put_w_req (origin_addr, origin_count,
|
|
|
|
origin_dt, target, target_disp,
|
|
|
|
target_count, target_dt, win, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
ompi_osc_rdma_accumulate_w_req (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_op_t *op, ompi_win_t *win,
|
|
|
|
ompi_osc_rdma_request_t *request)
|
2006-07-18 02:08:55 +04:00
|
|
|
{
|
|
|
|
int ret;
|
2007-05-24 19:41:24 +04:00
|
|
|
ompi_osc_rdma_module_t *module = GET_MODULE(win);
|
2014-02-25 21:36:43 +04:00
|
|
|
ompi_proc_t *proc = ompi_comm_peer_lookup(module->comm, target);
|
|
|
|
ompi_osc_rdma_frag_t *frag;
|
|
|
|
ompi_osc_rdma_header_acc_t *header;
|
|
|
|
size_t ddt_len, payload_len, frag_len;
|
|
|
|
char *ptr;
|
|
|
|
bool is_long_msg = false;
|
|
|
|
const void *packed_ddt;
|
|
|
|
int tag;
|
|
|
|
|
|
|
|
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
|
|
|
|
"acc: 0x%lx, %d, %s, %d, %d, %d, %s, %s, %s",
|
|
|
|
(unsigned long) origin_addr, origin_count,
|
|
|
|
origin_dt->name, target, (int) target_disp,
|
|
|
|
target_count, target_dt->name, op->o_name,
|
|
|
|
win->w_name));
|
|
|
|
|
|
|
|
/* short-circuit case */
|
|
|
|
if (0 == origin_count || 0 == target_count) {
|
|
|
|
if (request) {
|
|
|
|
ompi_osc_rdma_request_complete (request, MPI_SUCCESS);
|
|
|
|
}
|
2006-07-18 02:08:55 +04:00
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
return OMPI_SUCCESS;
|
2006-09-22 00:49:15 +04:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
/* optimize the self case. TODO: optimize the local case */
|
|
|
|
if (ompi_comm_rank (module->comm) == target) {
|
|
|
|
return ompi_osc_rdma_acc_self (origin_addr, origin_count, origin_dt,
|
|
|
|
target_disp, target_count, target_dt,
|
|
|
|
op, module, request);
|
2006-07-18 02:08:55 +04:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
/* Compute datatype and payload lengths. Note that the datatype description
|
|
|
|
* must fit in a single frag */
|
|
|
|
ddt_len = ompi_datatype_pack_description_length(target_dt);
|
|
|
|
payload_len = origin_dt->super.size * origin_count;
|
|
|
|
|
|
|
|
OPAL_THREAD_LOCK(&module->lock);
|
|
|
|
|
|
|
|
frag_len = sizeof(ompi_osc_rdma_header_acc_t) + ddt_len + payload_len;
|
|
|
|
ret = ompi_osc_rdma_frag_alloc(module, target, frag_len, &frag, &ptr);
|
|
|
|
if (OMPI_SUCCESS != ret) {
|
|
|
|
frag_len = sizeof(ompi_osc_rdma_header_acc_t) + ddt_len;
|
|
|
|
ret = ompi_osc_rdma_frag_alloc(module, target, frag_len, &frag, &ptr);
|
|
|
|
if (OMPI_SUCCESS != ret) {
|
|
|
|
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
|
|
|
|
"acc: out of resource error while trying to allocate a fragment"));
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
is_long_msg = true;
|
|
|
|
tag = get_tag (module);
|
|
|
|
}
|
|
|
|
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
|
|
|
|
header = (ompi_osc_rdma_header_acc_t*) ptr;
|
|
|
|
header->base.flags = 0;
|
|
|
|
header->len = frag_len;
|
|
|
|
header->count = target_count;
|
|
|
|
header->displacement = target_disp;
|
|
|
|
header->op = op->o_f_to_c_index;
|
|
|
|
ptr += sizeof(ompi_osc_rdma_header_acc_t);
|
|
|
|
|
|
|
|
ret = ompi_datatype_get_pack_description(target_dt, &packed_ddt);
|
|
|
|
memcpy((unsigned char*) ptr, packed_ddt, ddt_len);
|
|
|
|
ptr += ddt_len;
|
|
|
|
|
|
|
|
if (!is_long_msg) {
|
|
|
|
header->base.type = OMPI_OSC_RDMA_HDR_TYPE_ACC;
|
|
|
|
|
|
|
|
osc_rdma_copy_for_send (ptr, payload_len, origin_addr, proc,
|
|
|
|
origin_count, origin_dt);
|
|
|
|
|
|
|
|
/* the user's buffer is no longer needed so mark the request as
|
|
|
|
* complete. */
|
|
|
|
if (request) {
|
|
|
|
ompi_osc_rdma_request_complete (request, MPI_SUCCESS);
|
2006-07-18 02:08:55 +04:00
|
|
|
}
|
|
|
|
} else {
|
2014-02-25 21:36:43 +04:00
|
|
|
header->base.type = OMPI_OSC_RDMA_HDR_TYPE_ACC_LONG;
|
|
|
|
|
|
|
|
header->tag = tag;
|
|
|
|
|
|
|
|
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
|
|
|
|
"acc: starting long accumulate with tag %d", tag));
|
|
|
|
|
|
|
|
/* increment the outgoing send count */
|
|
|
|
ompi_osc_signal_outgoing (module, target, 1);
|
|
|
|
|
|
|
|
if (request) {
|
|
|
|
request->outstanding_requests = 1;
|
|
|
|
ret = ompi_osc_rdma_isend_w_cb (origin_addr, origin_count, origin_dt,
|
|
|
|
target, tag, module->comm, ompi_osc_rdma_req_comm_complete,
|
|
|
|
request);
|
|
|
|
} else {
|
|
|
|
ret = ompi_osc_rdma_component_isend (module, origin_addr, origin_count, origin_dt, target, tag,
|
|
|
|
module->comm);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OMPI_SUCCESS != ret) {
|
|
|
|
OPAL_OUTPUT_VERBOSE((25, ompi_osc_base_framework.framework_output,
|
|
|
|
"acc: send failed with eror %d", ret));
|
|
|
|
}
|
2006-07-18 02:08:55 +04:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
/* mark the fragment as valid */
|
|
|
|
if (OPAL_LIKELY(OMPI_SUCCESS == ret)) {
|
|
|
|
header->base.flags |= OMPI_OSC_RDMA_HDR_FLAG_VALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
OPAL_THREAD_LOCK(&module->lock);
|
|
|
|
|
|
|
|
ret = ompi_osc_rdma_frag_finish(module, frag);
|
|
|
|
|
|
|
|
if (request) {
|
|
|
|
/* need to flush now in case the caller decides to wait on the request */
|
|
|
|
ompi_osc_rdma_frag_flush_target (module, target);
|
|
|
|
}
|
|
|
|
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
|
2006-07-18 02:08:55 +04:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-02-25 21:36:43 +04:00
|
|
|
ompi_osc_rdma_accumulate(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_op_t *op, ompi_win_t *win)
|
|
|
|
{
|
|
|
|
return ompi_osc_rdma_accumulate_w_req (origin_addr, origin_count, origin_dt,
|
|
|
|
target, target_disp, target_count,
|
|
|
|
target_dt, op, win, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ompi_osc_rdma_compare_and_swap (void *origin_addr, void *compare_addr,
|
|
|
|
void *result_addr, struct ompi_datatype_t *dt,
|
|
|
|
int target, OPAL_PTRDIFF_TYPE target_disp,
|
|
|
|
struct ompi_win_t *win)
|
2006-07-18 02:08:55 +04:00
|
|
|
{
|
2014-02-25 21:36:43 +04:00
|
|
|
ompi_osc_rdma_module_t *module = GET_MODULE(win);
|
|
|
|
ompi_proc_t *proc = ompi_comm_peer_lookup(module->comm, target);
|
|
|
|
ompi_osc_rdma_frag_t *frag;
|
|
|
|
ompi_osc_rdma_header_cswap_t *header;
|
|
|
|
size_t ddt_len, payload_len, frag_len;
|
|
|
|
ompi_osc_rdma_request_t *request;
|
|
|
|
const void *packed_ddt;
|
|
|
|
int ret, tag;
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
|
|
|
|
"cswap: 0x%lx, 0x%lx, 0x%lx, %s, %d, %d, %s",
|
|
|
|
(unsigned long) origin_addr, (unsigned long) compare_addr,
|
|
|
|
(unsigned long) result_addr, dt->name, target, (int) target_disp,
|
|
|
|
win->w_name));
|
|
|
|
|
|
|
|
/* optimize self case. TODO: optimize local case */
|
|
|
|
if (ompi_comm_rank (module->comm) == target) {
|
|
|
|
return ompi_osc_rdma_cas_self (origin_addr, compare_addr, result_addr, dt, target_disp,
|
|
|
|
module);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* compare-and-swaps are always request based, so that we know where to land the data */
|
|
|
|
OMPI_OSC_RDMA_REQUEST_ALLOC(win, request);
|
|
|
|
if (NULL == request) {
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
request->type = OMPI_OSC_RDMA_HDR_TYPE_CSWAP;
|
|
|
|
request->origin_addr = origin_addr;
|
|
|
|
request->internal = true;
|
|
|
|
OBJ_RETAIN(dt);
|
|
|
|
request->origin_dt = dt;
|
|
|
|
|
|
|
|
/* Compute datatype and payload lengths. Note that the datatype description
|
|
|
|
* must fit in a single frag. It should be small in this case. */
|
|
|
|
ddt_len = ompi_datatype_pack_description_length(dt);
|
|
|
|
|
|
|
|
/* we need to send both the origin and compare buffers */
|
|
|
|
payload_len = dt->super.size * 2;
|
|
|
|
|
|
|
|
OPAL_THREAD_LOCK(&module->lock);
|
|
|
|
|
|
|
|
frag_len = sizeof(ompi_osc_rdma_header_cswap_t) + ddt_len + payload_len;
|
|
|
|
ret = ompi_osc_rdma_frag_alloc(module, target, frag_len, &frag, &ptr);
|
|
|
|
if (OMPI_SUCCESS != ret) {
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
tag = get_tag (module);
|
|
|
|
ompi_osc_signal_outgoing (module, target, 1);
|
|
|
|
|
|
|
|
header = (ompi_osc_rdma_header_cswap_t *) ptr;
|
|
|
|
header->base.type = OMPI_OSC_RDMA_HDR_TYPE_CSWAP;
|
|
|
|
header->base.flags = OMPI_OSC_RDMA_HDR_FLAG_VALID;
|
|
|
|
header->len = frag_len;
|
|
|
|
header->displacement = target_disp;
|
|
|
|
header->tag = tag;
|
|
|
|
ptr += sizeof(ompi_osc_rdma_header_cswap_t);
|
|
|
|
|
|
|
|
ret = ompi_datatype_get_pack_description(dt, &packed_ddt);
|
|
|
|
memcpy((unsigned char*) ptr, packed_ddt, ddt_len);
|
|
|
|
ptr += ddt_len;
|
|
|
|
|
|
|
|
/* pack the origin and compare data */
|
|
|
|
osc_rdma_copy_for_send (ptr, dt->super.size, origin_addr, proc, 1, dt);
|
|
|
|
ptr += dt->super.size;
|
|
|
|
osc_rdma_copy_for_send (ptr, dt->super.size, compare_addr, proc, 1, dt);
|
|
|
|
|
|
|
|
request->outstanding_requests = 1;
|
|
|
|
ret = ompi_osc_rdma_irecv_w_cb (result_addr, 1, dt, target, tag, module->comm,
|
|
|
|
NULL, ompi_osc_rdma_req_comm_complete, request);
|
|
|
|
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ompi_osc_rdma_frag_finish(module, frag);
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ompi_osc_rdma_fetch_and_op(void *origin_addr, void *result_addr,
|
|
|
|
struct ompi_datatype_t *dt, int target,
|
|
|
|
OPAL_PTRDIFF_TYPE target_disp, struct ompi_op_t *op,
|
|
|
|
struct ompi_win_t *win)
|
|
|
|
{
|
|
|
|
return ompi_osc_rdma_get_accumulate(origin_addr, 1, dt, result_addr, 1, dt,
|
|
|
|
target, target_disp, 1, dt, op, win);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ompi_osc_rdma_rput(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, struct ompi_request_t **request)
|
|
|
|
{
|
|
|
|
ompi_osc_rdma_request_t *rdma_request;
|
2006-07-18 02:08:55 +04:00
|
|
|
int ret;
|
2014-02-25 21:36:43 +04:00
|
|
|
|
|
|
|
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
|
|
|
|
"rput: 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));
|
|
|
|
|
|
|
|
OMPI_OSC_RDMA_REQUEST_ALLOC(win, rdma_request);
|
|
|
|
if (NULL == rdma_request) {
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* short-circuit case */
|
|
|
|
if (0 == origin_count || 0 == target_count) {
|
|
|
|
ompi_osc_rdma_request_complete (rdma_request, MPI_SUCCESS);
|
|
|
|
*request = &rdma_request->super;
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
rdma_request->type = OMPI_OSC_RDMA_HDR_TYPE_PUT;
|
|
|
|
|
|
|
|
ret = ompi_osc_rdma_put_w_req (origin_addr, origin_count, origin_dt, target,
|
|
|
|
target_disp, target_count, target_dt, win,
|
|
|
|
rdma_request);
|
|
|
|
if (OMPI_SUCCESS != ret) {
|
|
|
|
OMPI_OSC_RDMA_REQUEST_RETURN(rdma_request);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
*request = (ompi_request_t *) rdma_request;
|
|
|
|
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int ompi_osc_rdma_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;
|
2007-05-24 19:41:24 +04:00
|
|
|
ompi_osc_rdma_module_t *module = GET_MODULE(win);
|
2014-02-25 21:36:43 +04:00
|
|
|
ompi_osc_rdma_frag_t *frag;
|
|
|
|
ompi_osc_rdma_header_get_t *header;
|
|
|
|
size_t ddt_len, frag_len;
|
|
|
|
char *ptr;
|
|
|
|
const void *packed_ddt;
|
|
|
|
ompi_osc_rdma_request_t *rdma_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));
|
|
|
|
|
|
|
|
/* gets are always request based, so that we know where to land the data */
|
|
|
|
OMPI_OSC_RDMA_REQUEST_ALLOC(win, rdma_request);
|
|
|
|
if (NULL == rdma_request) {
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
rdma_request->internal = release_req;
|
|
|
|
|
|
|
|
/* short-circuit case */
|
|
|
|
if (0 == origin_count || 0 == target_count) {
|
|
|
|
ompi_osc_rdma_request_complete (rdma_request, MPI_SUCCESS);
|
|
|
|
*request = &rdma_request->super;
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* optimize self communication. TODO: optimize local communication */
|
|
|
|
if (ompi_comm_rank (module->comm) == target) {
|
|
|
|
*request = &rdma_request->super;
|
|
|
|
return ompi_osc_rdma_get_self (origin_addr, origin_count, origin_dt,
|
|
|
|
target_disp, target_count, target_dt,
|
|
|
|
module, rdma_request);
|
|
|
|
}
|
2006-07-18 02:08:55 +04:00
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
rdma_request->type = OMPI_OSC_RDMA_HDR_TYPE_GET;
|
|
|
|
rdma_request->origin_addr = origin_addr;
|
|
|
|
rdma_request->origin_count = origin_count;
|
|
|
|
OBJ_RETAIN(origin_dt);
|
|
|
|
rdma_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);
|
|
|
|
|
|
|
|
OPAL_THREAD_LOCK(&module->lock);
|
|
|
|
|
|
|
|
frag_len = sizeof(ompi_osc_rdma_header_get_t) + ddt_len;
|
|
|
|
ret = ompi_osc_rdma_frag_alloc(module, target, frag_len, &frag, &ptr);
|
|
|
|
if (OMPI_SUCCESS != ret) {
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
2006-09-22 00:49:15 +04:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
tag = get_tag (module);
|
|
|
|
|
|
|
|
/* for bookkeeping the get is "outgoing" */
|
|
|
|
ompi_osc_signal_outgoing (module, target, 1);
|
|
|
|
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
|
|
|
|
header = (ompi_osc_rdma_header_get_t*) ptr;
|
|
|
|
header->base.type = OMPI_OSC_RDMA_HDR_TYPE_GET;
|
|
|
|
header->base.flags = 0;
|
|
|
|
header->len = frag_len;
|
|
|
|
header->count = target_count;
|
|
|
|
header->displacement = target_disp;
|
|
|
|
header->tag = tag;
|
|
|
|
ptr += sizeof(ompi_osc_rdma_header_get_t);
|
|
|
|
|
|
|
|
ret = ompi_datatype_get_pack_description(target_dt, &packed_ddt);
|
|
|
|
memcpy((unsigned char*) ptr, packed_ddt, ddt_len);
|
|
|
|
ptr += ddt_len;
|
|
|
|
|
|
|
|
if (OMPI_SUCCESS == ret) {
|
|
|
|
header->base.flags |= OMPI_OSC_RDMA_HDR_FLAG_VALID;
|
|
|
|
*request = &rdma_request->super;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO -- store the request somewhere so we can cancel it on error */
|
|
|
|
rdma_request->outstanding_requests = 1;
|
|
|
|
ret = ompi_osc_rdma_irecv_w_cb (origin_addr, origin_count, origin_dt, target, tag,
|
|
|
|
module->comm, NULL, ompi_osc_rdma_req_comm_complete, rdma_request);
|
|
|
|
|
|
|
|
OPAL_THREAD_LOCK(&module->lock);
|
|
|
|
ret = ompi_osc_rdma_frag_finish(module, frag);
|
|
|
|
|
|
|
|
if (!release_req) {
|
|
|
|
/* need to flush now in case the caller decides to wait on the request */
|
|
|
|
ompi_osc_rdma_frag_flush_target (module, target);
|
|
|
|
}
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ompi_osc_rdma_rget (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,
|
|
|
|
struct ompi_request_t **request)
|
|
|
|
{
|
|
|
|
/* NTH: need to check for a passive access epoch and return the appropriate error if nececcesary */
|
|
|
|
return ompi_osc_rdma_rget_internal (origin_addr, origin_count, origin_dt, target, target_disp,
|
|
|
|
target_count, target_dt, win, false, request);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ompi_osc_rdma_get (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)
|
|
|
|
{
|
|
|
|
ompi_request_t *request;
|
|
|
|
|
|
|
|
return ompi_osc_rdma_rget_internal (origin_addr, origin_count, origin_dt, target, target_disp,
|
|
|
|
target_count, target_dt, win, true, &request);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ompi_osc_rdma_raccumulate(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_op_t *op,
|
|
|
|
struct ompi_win_t *win, struct ompi_request_t **request)
|
|
|
|
{
|
|
|
|
ompi_osc_rdma_request_t *rdma_request;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
|
|
|
|
"raccumulate: 0x%lx, %d, %s, %d, %d, %d, %s, %s, %s",
|
|
|
|
(unsigned long) origin_addr, origin_count,
|
|
|
|
origin_dt->name, target, (int) target_disp,
|
|
|
|
target_count, target_dt->name, op->o_name,
|
|
|
|
win->w_name));
|
|
|
|
|
|
|
|
OMPI_OSC_RDMA_REQUEST_ALLOC(win, rdma_request);
|
|
|
|
if (NULL == rdma_request) {
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
2006-07-18 02:08:55 +04:00
|
|
|
}
|
|
|
|
|
2014-02-25 21:36:43 +04:00
|
|
|
/* short-circuit case */
|
2006-07-18 02:08:55 +04:00
|
|
|
if (0 == origin_count || 0 == target_count) {
|
2014-02-25 21:36:43 +04:00
|
|
|
ompi_osc_rdma_request_complete (rdma_request, MPI_SUCCESS);
|
|
|
|
*request = (ompi_request_t *) rdma_request;
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
rdma_request->type = OMPI_OSC_RDMA_HDR_TYPE_ACC;
|
|
|
|
|
|
|
|
ret = ompi_osc_rdma_accumulate_w_req (origin_addr, origin_count, origin_dt, target,
|
|
|
|
target_disp, target_count, target_dt, op, win,
|
|
|
|
rdma_request);
|
|
|
|
if (OMPI_SUCCESS != ret) {
|
|
|
|
OMPI_OSC_RDMA_REQUEST_RETURN(rdma_request);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
*request = (ompi_request_t *) rdma_request;
|
|
|
|
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline
|
|
|
|
int ompi_osc_rdma_rget_accumulate_internal (void *origin_addr, int origin_count,
|
|
|
|
struct ompi_datatype_t *origin_datatype,
|
|
|
|
void *result_addr, int result_count,
|
|
|
|
struct ompi_datatype_t *result_datatype,
|
|
|
|
int target_rank, MPI_Aint target_disp,
|
|
|
|
int target_count, struct ompi_datatype_t *target_datatype,
|
|
|
|
struct ompi_op_t *op, struct ompi_win_t *win,
|
|
|
|
bool release_req, struct ompi_request_t **request)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
ompi_osc_rdma_module_t *module = GET_MODULE(win);
|
|
|
|
ompi_proc_t *proc = ompi_comm_peer_lookup(module->comm, target_rank);
|
|
|
|
ompi_osc_rdma_frag_t *frag;
|
|
|
|
ompi_osc_rdma_header_get_acc_t *header;
|
|
|
|
size_t ddt_len, payload_len, frag_len;
|
|
|
|
char *ptr;
|
|
|
|
bool is_long_msg = false;
|
|
|
|
const void *packed_ddt;
|
|
|
|
int tag;
|
|
|
|
ompi_osc_rdma_request_t *rdma_request;
|
|
|
|
|
|
|
|
OPAL_OUTPUT_VERBOSE((50, ompi_osc_base_framework.framework_output,
|
|
|
|
"rget_acc: 0x%lx, %d, %s, 0x%lx, %d, %s, 0x%x, %d, %d, %s, %s, %s",
|
|
|
|
(unsigned long) origin_addr, origin_count, origin_datatype->name,
|
|
|
|
(unsigned long) result_addr, result_count, result_datatype->name,
|
|
|
|
target_rank, (int) target_disp, target_count, target_datatype->name,
|
|
|
|
op->o_name, win->w_name));
|
|
|
|
|
|
|
|
/* get_accumulates are always request based, so that we know where to land the data */
|
|
|
|
OMPI_OSC_RDMA_REQUEST_ALLOC(win, rdma_request);
|
|
|
|
if (OPAL_UNLIKELY(NULL == rdma_request)) {
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
rdma_request->internal = release_req;
|
|
|
|
|
|
|
|
/* short-circuit case. note that origin_count may be 0 if op is MPI_NO_OP */
|
|
|
|
if (0 == result_count || 0 == target_count) {
|
|
|
|
ompi_osc_rdma_request_complete (rdma_request, MPI_SUCCESS);
|
|
|
|
*request = &rdma_request->super;
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* optimize the self case. TODO: optimize the local case */
|
|
|
|
if (ompi_comm_rank (module->comm) == target_rank) {
|
|
|
|
*request = &rdma_request->super;
|
|
|
|
return ompi_osc_rdma_gacc_self (origin_addr, origin_count, origin_datatype,
|
|
|
|
result_addr, result_count, result_datatype,
|
|
|
|
target_disp, target_count, target_datatype,
|
|
|
|
op, module, rdma_request);
|
|
|
|
}
|
|
|
|
|
|
|
|
rdma_request->type = OMPI_OSC_RDMA_HDR_TYPE_GET_ACC;
|
|
|
|
rdma_request->origin_addr = origin_addr;
|
|
|
|
rdma_request->origin_count = origin_count;
|
|
|
|
OBJ_RETAIN(origin_datatype);
|
|
|
|
rdma_request->origin_dt = origin_datatype;
|
|
|
|
|
|
|
|
/* Compute datatype and payload lengths. Note that the datatype description
|
|
|
|
* must fit in a single frag */
|
|
|
|
ddt_len = ompi_datatype_pack_description_length(target_datatype);
|
|
|
|
|
|
|
|
if (&ompi_mpi_op_no_op.op != op) {
|
|
|
|
payload_len = origin_datatype->super.size * origin_count;
|
|
|
|
} else {
|
|
|
|
payload_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
OPAL_THREAD_LOCK(&module->lock);
|
|
|
|
|
|
|
|
frag_len = sizeof(*header) + ddt_len + payload_len;
|
|
|
|
ret = ompi_osc_rdma_frag_alloc(module, target_rank, frag_len, &frag, &ptr);
|
|
|
|
if (OMPI_SUCCESS != ret) {
|
|
|
|
frag_len = sizeof(*header) + ddt_len;
|
|
|
|
ret = ompi_osc_rdma_frag_alloc(module, target_rank, frag_len, &frag, &ptr);
|
|
|
|
if (OMPI_SUCCESS != ret) {
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
is_long_msg = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
tag = get_tag (module);
|
|
|
|
|
|
|
|
/* If this is a long message then we need two completions before the
|
|
|
|
* request is complete (1 for the send, 1 for the receive) */
|
|
|
|
rdma_request->outstanding_requests = 1 + is_long_msg;
|
|
|
|
|
|
|
|
/* increment the number of outgoing fragments */
|
|
|
|
ompi_osc_signal_outgoing (module, target_rank, rdma_request->outstanding_requests);
|
|
|
|
|
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
|
|
|
|
|
|
|
header = (ompi_osc_rdma_header_get_acc_t *) ptr;
|
|
|
|
header->base.flags = 0;
|
|
|
|
header->len = frag_len;
|
|
|
|
header->count = target_count;
|
|
|
|
header->displacement = target_disp;
|
|
|
|
header->op = op->o_f_to_c_index;
|
|
|
|
header->tag = tag;
|
|
|
|
ptr = (char *)(header + 1);
|
|
|
|
|
|
|
|
ret = ompi_datatype_get_pack_description(target_datatype, &packed_ddt);
|
|
|
|
memcpy((unsigned char*) ptr, packed_ddt, ddt_len);
|
|
|
|
ptr += ddt_len;
|
|
|
|
|
|
|
|
ret = ompi_osc_rdma_irecv_w_cb (result_addr, result_count, result_datatype, target_rank, tag,
|
|
|
|
module->comm, NULL, ompi_osc_rdma_req_comm_complete, rdma_request);
|
|
|
|
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!is_long_msg) {
|
|
|
|
header->base.type = OMPI_OSC_RDMA_HDR_TYPE_GET_ACC;
|
|
|
|
|
|
|
|
if (&ompi_mpi_op_no_op.op != op) {
|
|
|
|
osc_rdma_copy_for_send (ptr, payload_len, origin_addr, proc, origin_count,
|
|
|
|
origin_datatype);
|
2006-07-18 02:08:55 +04:00
|
|
|
}
|
|
|
|
} else {
|
2014-02-25 21:36:43 +04:00
|
|
|
header->base.type = OMPI_OSC_RDMA_HDR_TYPE_GET_ACC_LONG;
|
|
|
|
|
|
|
|
ret = ompi_osc_rdma_isend_w_cb (origin_addr, origin_count, origin_datatype, target_rank,
|
|
|
|
tag, module->comm, ompi_osc_rdma_req_comm_complete, rdma_request);
|
|
|
|
if (OMPI_SUCCESS != ret) goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (OMPI_SUCCESS == ret) {
|
|
|
|
header->base.flags |= OMPI_OSC_RDMA_HDR_FLAG_VALID;
|
|
|
|
*request = (ompi_request_t *) rdma_request;
|
|
|
|
}
|
|
|
|
|
|
|
|
OPAL_THREAD_LOCK(&module->lock);
|
|
|
|
ret = ompi_osc_rdma_frag_finish(module, frag);
|
|
|
|
|
|
|
|
if (!release_req) {
|
|
|
|
/* need to flush now in case the caller decides to wait on the request */
|
|
|
|
ompi_osc_rdma_frag_flush_target (module, target_rank);
|
2006-07-18 02:08:55 +04:00
|
|
|
}
|
2014-02-25 21:36:43 +04:00
|
|
|
OPAL_THREAD_UNLOCK(&module->lock);
|
2006-07-18 02:08:55 +04:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2014-02-25 21:36:43 +04:00
|
|
|
|
|
|
|
int ompi_osc_rdma_get_accumulate(void *origin_addr, int origin_count,
|
|
|
|
struct ompi_datatype_t *origin_dt,
|
|
|
|
void *result_addr, int result_count,
|
|
|
|
struct ompi_datatype_t *result_dt,
|
|
|
|
int target, MPI_Aint target_disp,
|
|
|
|
int target_count, struct ompi_datatype_t *target_dt,
|
|
|
|
struct ompi_op_t *op, struct ompi_win_t *win)
|
|
|
|
{
|
|
|
|
ompi_request_t *request;
|
|
|
|
|
|
|
|
return ompi_osc_rdma_rget_accumulate_internal (origin_addr, origin_count, origin_dt,
|
|
|
|
result_addr, result_count, result_dt,
|
|
|
|
target, target_disp, target_count,
|
|
|
|
target_dt, op, win, true, &request);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ompi_osc_rdma_rget_accumulate(void *origin_addr, int origin_count,
|
|
|
|
struct ompi_datatype_t *origin_dt,
|
|
|
|
void *result_addr, int result_count,
|
|
|
|
struct ompi_datatype_t *result_dt,
|
|
|
|
int target, MPI_Aint target_disp,
|
|
|
|
int target_count, struct ompi_datatype_t *target_dt,
|
|
|
|
struct ompi_op_t *op, struct ompi_win_t *win,
|
|
|
|
ompi_request_t **request)
|
|
|
|
{
|
|
|
|
return ompi_osc_rdma_rget_accumulate_internal (origin_addr, origin_count, origin_dt,
|
|
|
|
result_addr, result_count, result_dt,
|
|
|
|
target, target_disp, target_count,
|
|
|
|
target_dt, op, win, false, request);
|
|
|
|
}
|