* update MPI_ACCUMULATE to perform it's parameter checking based on what
MPI-2:6.3.4 says about reduction operations * Have the point-to-point one-sided component spew a warning and return an error if a non-predefined datatype is used with an MPI_OP other than MPI_REPLACE. Yes, this violates the MPI standard, but it's the best we can do until George and I implement support for figuring out where all the locations to update are.. This commit was SVN r9134.
Этот коммит содержится в:
родитель
06def0b2d6
Коммит
27b8430e8f
@ -15,6 +15,9 @@
|
||||
*/
|
||||
|
||||
#include "ompi_config.h"
|
||||
#include "mpi.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "osc_pt2pt.h"
|
||||
#include "osc_pt2pt_sendreq.h"
|
||||
@ -44,6 +47,13 @@ ompi_osc_pt2pt_module_accumulate(void *origin_addr, int origin_count,
|
||||
int ret;
|
||||
ompi_osc_pt2pt_sendreq_t *sendreq;
|
||||
|
||||
if (!ompi_ddt_is_predefined(target_dt)) {
|
||||
fprintf(stderr, "MPI_Accumulate currently does not support reductions\n");
|
||||
fprintf(stderr, "with any user-defined types. This will be rectified\n");
|
||||
fprintf(stderr, "in a future release.\n");
|
||||
return MPI_ERR_UNSUPPORTED_OPERATION;
|
||||
}
|
||||
|
||||
/* create sendreq */
|
||||
ret = ompi_osc_pt2pt_sendreq_alloc_init(OMPI_OSC_PT2PT_ACC,
|
||||
origin_addr,
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "ompi/mca/osc/osc.h"
|
||||
#include "ompi/op/op.h"
|
||||
#include "ompi/datatype/datatype.h"
|
||||
#include "ompi/datatype/datatype_internal.h"
|
||||
|
||||
#if OMPI_HAVE_WEAK_SYMBOLS && OMPI_PROFILING_DEFINES
|
||||
#pragma weak MPI_Accumulate = PMPI_Accumulate
|
||||
@ -41,7 +42,6 @@ int MPI_Accumulate(void *origin_addr, int origin_count, MPI_Datatype origin_data
|
||||
{
|
||||
int rc;
|
||||
ompi_win_t *ompi_win = (ompi_win_t*) win;
|
||||
char *msg;
|
||||
|
||||
if (target_rank == MPI_PROC_NULL) return MPI_SUCCESS;
|
||||
|
||||
@ -58,21 +58,73 @@ int MPI_Accumulate(void *origin_addr, int origin_count, MPI_Datatype origin_data
|
||||
rc = MPI_ERR_RANK;
|
||||
} else if (MPI_OP_NULL == op) {
|
||||
rc = MPI_ERR_OP;
|
||||
} else if (op != &ompi_mpi_op_replace &&
|
||||
!ompi_op_is_valid(op, target_datatype, &msg, FUNC_NAME)) {
|
||||
int ret = OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_OP, msg);
|
||||
free(msg);
|
||||
return ret;
|
||||
} else if (0 == (ompi_win_get_mode(win) & OMPI_WIN_ACCESS_EPOCH)) {
|
||||
rc = MPI_ERR_RMA_CONFLICT;
|
||||
} else {
|
||||
OMPI_CHECK_DATATYPE_FOR_SEND(rc, origin_datatype, origin_count);
|
||||
}
|
||||
OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME);
|
||||
|
||||
/* While technically the standard probably requires that the
|
||||
datatypes used with MPI_REPLACE conform to all the rules
|
||||
for other reduction operators, we don't require such
|
||||
behaivor, as checking for it is expensive here and we don't
|
||||
care in implementation.. */
|
||||
if (op != &ompi_mpi_op_replace) {
|
||||
ompi_datatype_t *op_check_dt;
|
||||
char *msg;
|
||||
|
||||
/* ACCUMULATE, unlike REDUCE, can use with derived
|
||||
datatypes with predefinied operations, with some
|
||||
restrictions outlined in MPI-2:6.3.4. The derived
|
||||
datatype must be composed entirley from one predefined
|
||||
datatype (so you can do all the construction you want,
|
||||
but at the bottom, you can only use one datatype, say,
|
||||
MPI_INT). If the datatype at the target isn't
|
||||
predefined, then make sure it's composed of only one
|
||||
datatype, and check that datatype against
|
||||
ompi_op_is_valid(). */
|
||||
if (ompi_ddt_is_predefined(target_datatype)) {
|
||||
op_check_dt = target_datatype;
|
||||
} else {
|
||||
int i, index = -1, num_found = 0;
|
||||
uint64_t mask = 1;
|
||||
|
||||
for (i = 0 ; i < DT_MAX_PREDEFINED ; ++i) {
|
||||
if (target_datatype->bdt_used & mask) {
|
||||
num_found++;
|
||||
index = i;
|
||||
}
|
||||
mask *= 2;
|
||||
}
|
||||
if (index < 0 || num_found > 1) {
|
||||
/* this is an erroneous datatype. Let
|
||||
ompi_op_is_valid tell the user that */
|
||||
op_check_dt = target_datatype;
|
||||
} else {
|
||||
/* datatype passes muster as far as restrictions
|
||||
in MPI-2:6.3.4. Is the primitive ok with the
|
||||
op? Unfortunately have to cast away
|
||||
constness... */
|
||||
op_check_dt = (ompi_datatype_t*)
|
||||
ompi_ddt_basicDatatypes[index];
|
||||
}
|
||||
}
|
||||
if (!ompi_op_is_valid(op, op_check_dt, &msg, FUNC_NAME)) {
|
||||
int ret = OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_OP, msg);
|
||||
free(msg);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = ompi_win->w_osc_module->osc_accumulate(origin_addr, origin_count, origin_datatype,
|
||||
target_rank, target_disp, target_count,
|
||||
target_datatype, op, win);
|
||||
rc = ompi_win->w_osc_module->osc_accumulate(origin_addr,
|
||||
origin_count,
|
||||
origin_datatype,
|
||||
target_rank,
|
||||
target_disp,
|
||||
target_count,
|
||||
target_datatype,
|
||||
op, win);
|
||||
OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME);
|
||||
}
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user