diff --git a/CHANGES b/CHANGES index 7d07c429473..18766439d46 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,32 @@ +=============================================================================== + Changes in 4.1.1 +=============================================================================== + +# Update embedded UCX module to 1.13.1. Fixes a build issue with + binutils >= 2.39. + +# Update yaksa module. Support explicit NVCC setting by the user. Fixes + a build issue when there is no libtool available in PATH. + +# Fix ch4:ucx initialization when configured with + --enable-ch4-vci-method=implicit. + +# Fix potential error handler leak during MPI_SESSION_FINALIZE + +# Fix value of MPI_UNDEFINED in mpif.h binding + +# Fix MPI_IALLTOALLW with MPI_IN_PLACE + +# Fix send attribute handling in IPC path + +# Fix a bug in persistent MPI_ALLGATHER + +# Fix tests for use with non-MPICH libraries + +# Add missing MPI_T_ERR_NOT_ACCESSIBLE error code + +# Fix manpages for MPIX functions + =============================================================================== Changes in 4.1 =============================================================================== diff --git a/maint/local_python/binding_c.py b/maint/local_python/binding_c.py index 6b2068aafcd..0c54df70f8a 100644 --- a/maint/local_python/binding_c.py +++ b/maint/local_python/binding_c.py @@ -81,10 +81,8 @@ def dump_romio_reference(name): dump_function_internal(func, kind="normal") G.out.append("") - # NOTE: dump_manpage is now called inside dump_qmpi_wrappers - # Create the MPI and QMPI wrapper functions that will call the above, "real" version of the - # function in the MPII prefix + # function in the internal prefix dump_qmpi_wrappers(func, func['_is_large']) def get_func_file_path(func, root_dir): @@ -868,6 +866,9 @@ def dump_description(s): if l > 0: out.append(' ' + ' '.join(words[i0:])) # ---- + if not func['desc']: + # place holder to make the man page render + func['desc'] = "[short description]" out.append("/*D") out.append(" %s - %s" % (get_function_name(func, False), func['desc'])) out.append("") diff --git a/maint/local_python/binding_f77.py b/maint/local_python/binding_f77.py index 3803f972eea..b2cdae9411b 100644 --- a/maint/local_python/binding_f77.py +++ b/maint/local_python/binding_f77.py @@ -438,7 +438,11 @@ def dump_index_out(v): c_arg_list_B.append("&%s_i" % v) code_list_common.append("int %s_i;" % v) end_list_common.append("if (*ierr == MPI_SUCCESS) {") - end_list_common.append(" *%s = %s_i + 1;" % (v, v)) + end_list_common.append(" if (%s_i == MPI_UNDEFINED) {" % v) + end_list_common.append(" *%s = %s_i;" % (v, v)) + end_list_common.append(" } else {") + end_list_common.append(" *%s = %s_i + 1;" % (v, v)) + end_list_common.append(" }") end_list_common.append("}") def dump_string_len_inout(v): diff --git a/maint/version.m4 b/maint/version.m4 index 35dff33e817..b58eb641284 100644 --- a/maint/version.m4 +++ b/maint/version.m4 @@ -14,7 +14,7 @@ # changing this by playing with diversions, but then we would probably be # playing with autotools-fire. -m4_define([MPICH_VERSION_m4],[4.1])dnl +m4_define([MPICH_VERSION_m4],[4.1.1])dnl m4_define([MPICH_RELEASE_DATE_m4],[unreleased development copy])dnl # For libtool ABI versioning rules see: @@ -36,7 +36,7 @@ m4_define([MPICH_RELEASE_DATE_m4],[unreleased development copy])dnl # standard, and does not include MPIX_ functions and C++ bindings. # Use [0:0:0] for unstable (e.g. alpha and beta) releases. -# last version: 4.1 - 14:4:2 +# last version: 4.1.1 - 15:0:3 m4_define([libmpi_so_version_m4],[0:0:0])dnl diff --git a/src/binding/c/stream_api.txt b/src/binding/c/stream_api.txt index 093d16857ea..76f1a418577 100644 --- a/src/binding/c/stream_api.txt +++ b/src/binding/c/stream_api.txt @@ -1,39 +1,48 @@ # vim: set ft=c: MPIX_Stream_create: + .desc: Create a new stream object info: INFO, [info argument] stream: STREAM, direction=out, [stream object created] MPIX_Stream_free: + .desc: Free a stream object stream: STREAM, direction=inout, [stream object] MPIX_Stream_comm_create: + .desc: Create a new communicator with local stream attached comm: COMMUNICATOR, [communicator] stream: STREAM, [stream object] newcomm: COMMUNICATOR, direction=out, [new stream-associated communicator] MPIX_Stream_comm_create_multiplex: + .desc: Create a new communicator with multiple local streams attached comm: COMMUNICATOR, [communicator] count: ARRAY_LENGTH_NNI, [list length] array_of_streams: STREAM, length=count, [stream object array] newcomm: COMMUNICATOR, direction=out, [new stream-associated communicator] MPIX_Comm_get_stream: + .desc: Get the stream object that is attached to the communicator comm: COMMUNICATOR, [communicator] idx: INDEX stream: STREAM, direction=out, [stream object] MPIX_Stream_progress: stream: STREAM, [stream object] + .desc: Invoke progress on the given stream .impl: mpid MPIX_Start_progress_thread: + .desc: Start a progress thread that will poll progress on the given stream stream: STREAM, [stream object] MPIX_Stop_progress_thread: + .desc: Stop the progress thread that polls progress on the given stream stream: STREAM, [stream object] MPIX_Stream_send: + .desc: Send message from a specific local stream to a specific destination stream buf: BUFFER, constant=True, [initial address of send buffer] count: POLYXFER_NUM_ELEM_NNI, [number of elements in send buffer] datatype: DATATYPE, [datatype of each send buffer element] @@ -67,6 +76,7 @@ MPIX_Stream_send: } MPIX_Stream_isend: + .desc: Start a nonblocking send from a specific local stream to a specific remote stream buf: BUFFER, asynchronous=True, constant=True, [initial address of send buffer] count: POLYXFER_NUM_ELEM_NNI, [number of elements in send buffer] datatype: DATATYPE, [datatype of each send buffer element] @@ -98,6 +108,7 @@ MPIX_Stream_isend: } MPIX_Stream_recv: + .desc: Receive a message from a specific source stream to a specific local stream buf: BUFFER, direction=out, [initial address of receive buffer] count: POLYXFER_NUM_ELEM_NNI, [number of elements in receive buffer] datatype: DATATYPE, [datatype of each receive buffer element] @@ -134,6 +145,7 @@ MPIX_Stream_recv: } MPIX_Stream_irecv: + .desc: Start a nonblocking receive from a specific source stream to a specific local stream buf: BUFFER, direction=out, asynchronous=True, suppress=f08_intent, [initial address of receive buffer] count: POLYXFER_NUM_ELEM_NNI, [number of elements in receive buffer] datatype: DATATYPE, [datatype of each receive buffer element] @@ -159,6 +171,7 @@ MPIX_Stream_irecv: } MPIX_Send_enqueue: + .desc: Enqueue a send operation to a GPU stream that is associated with the local stream buf: BUFFER, constant=True, [initial address of send buffer] count: POLYXFER_NUM_ELEM_NNI, [number of elements in send buffer] datatype: DATATYPE, [datatype of each send buffer element] @@ -169,6 +182,7 @@ MPIX_Send_enqueue: .decl: MPIR_Send_enqueue_impl MPIX_Recv_enqueue: + .desc: Enqueue a receive operation to a GPU stream that is associated with the local stream buf: BUFFER, direction=out, [initial address of receive buffer] count: POLYXFER_NUM_ELEM_NNI, [number of elements in receive buffer] datatype: DATATYPE, [datatype of each receive buffer element] @@ -180,6 +194,7 @@ MPIX_Recv_enqueue: .decl: MPIR_Recv_enqueue_impl MPIX_Isend_enqueue: + .desc: Enqueue a nonblocking send operation to a GPU stream that is associated with the local stream buf: BUFFER, constant=True, [initial address of send buffer] count: POLYXFER_NUM_ELEM_NNI, [number of elements in send buffer] datatype: DATATYPE, [datatype of each send buffer element] @@ -191,6 +206,7 @@ MPIX_Isend_enqueue: .decl: MPIR_Isend_enqueue_impl MPIX_Irecv_enqueue: + .desc: Enqueue a nonblocking receive operation to a GPU stream that is associated with the local stream buf: BUFFER, direction=out, [initial address of receive buffer] count: POLYXFER_NUM_ELEM_NNI, [number of elements in receive buffer] datatype: DATATYPE, [datatype of each receive buffer element] @@ -202,12 +218,14 @@ MPIX_Irecv_enqueue: .decl: MPIR_Irecv_enqueue_impl MPIX_Wait_enqueue: + .desc: Enqueue a wait operation to a GPU stream that is associated with the local stream request: REQUEST, direction=inout, [request] status: STATUS, direction=out .impl: mpid .decl: MPIR_Wait_enqueue_impl MPIX_Waitall_enqueue: + .desc: Enqueue a waitall operation to a GPU stream that is associated with the local stream count: ARRAY_LENGTH_NNI, [lists length] array_of_requests: REQUEST, direction=inout, length=count, [array of requests] array_of_statuses: STATUS, direction=out, length=*, pointer=False, [array of status objects] @@ -220,6 +238,7 @@ MPIX_Waitall_enqueue: } MPIX_Allreduce_enqueue: + .desc: Enqueue an allreduce operation to a GPU stream that is associated with the local stream sendbuf: BUFFER, constant=True, [starting address of send buffer] recvbuf: BUFFER, direction=out, [starting address of receive buffer] count: POLYXFER_NUM_ELEM_NNI, [number of elements in send buffer] diff --git a/src/include/mpi.h.in b/src/include/mpi.h.in index c09af0d6fb4..48373ff5ed1 100644 --- a/src/include/mpi.h.in +++ b/src/include/mpi.h.in @@ -920,10 +920,11 @@ typedef int (MPIX_Grequest_wait_function)(int, void **, double, MPI_Status *); #define MPI_ERR_VALUE_TOO_LARGE 77 /* Value is too large to store */ #define MPI_T_ERR_NOT_SUPPORTED 78 /* Requested functionality not supported */ +#define MPI_T_ERR_NOT_ACCESSIBLE 79 /* Requested functionality not accessible */ #define MPI_ERR_LASTCODE 0x3fffffff /* Last valid error code for a predefined error class */ -#define MPICH_ERR_LAST_CLASS 78 /* It is also helpful to know the +#define MPICH_ERR_LAST_CLASS 79 /* It is also helpful to know the last valid class */ #define MPICH_ERR_FIRST_MPIX 100 /* Define a gap here because sock is diff --git a/src/mpi/coll/iallgather/iallgather_intra_sched_recursive_doubling.c b/src/mpi/coll/iallgather/iallgather_intra_sched_recursive_doubling.c index 81d670ebd5c..dd0ba4c217a 100644 --- a/src/mpi/coll/iallgather/iallgather_intra_sched_recursive_doubling.c +++ b/src/mpi/coll/iallgather/iallgather_intra_sched_recursive_doubling.c @@ -8,6 +8,7 @@ /* helper callbacks and associated state structures */ struct shared_state { int recvtype; + int recvcount; MPI_Aint curr_count; MPI_Aint last_recv_count; MPI_Status status; @@ -22,10 +23,11 @@ static int get_count(MPIR_Comm * comm, int tag, void *state) return MPI_SUCCESS; } -static int dtp_release_ref(MPIR_Comm * comm, int tag, void *state) +static int reset_shared_state(MPIR_Comm * comm, int tag, void *state) { - MPIR_Datatype *recv_dtp = state; - MPIR_Datatype_ptr_release(recv_dtp); + struct shared_state *ss = state; + ss->curr_count = ss->recvcount; + return MPI_SUCCESS; } @@ -53,7 +55,6 @@ int MPIR_Iallgather_intra_sched_recursive_doubling(const void *sendbuf, MPI_Aint int mask, tmp_mask, dst; int dst_tree_root, my_tree_root, tree_root; MPI_Aint recvtype_extent; - MPIR_Datatype *recv_dtp; comm_size = comm_ptr->local_size; rank = comm_ptr->rank; @@ -64,11 +65,6 @@ int MPIR_Iallgather_intra_sched_recursive_doubling(const void *sendbuf, MPI_Aint MPIR_Assert(!(comm_size & (comm_size - 1))); #endif /* HAVE_ERROR_CHECKING */ - recv_dtp = NULL; - if (!HANDLE_IS_BUILTIN(recvtype)) { - MPIR_Datatype_get_ptr(recvtype, recv_dtp); - } - MPIR_Datatype_get_extent_macro(recvtype, recvtype_extent); /* copy local data into recvbuf */ @@ -84,9 +80,7 @@ int MPIR_Iallgather_intra_sched_recursive_doubling(const void *sendbuf, MPI_Aint MPIR_ERR_CHKANDJUMP(!ss, mpi_errno, MPI_ERR_OTHER, "**nomem"); ss->curr_count = recvcount; ss->recvtype = recvtype; - /* ensure that recvtype doesn't disappear immediately after last _recv but before _cb */ - if (recv_dtp) - MPIR_Datatype_ptr_add_ref(recv_dtp); + ss->recvcount = recvcount; mask = 0x1; i = 0; @@ -205,10 +199,8 @@ int MPIR_Iallgather_intra_sched_recursive_doubling(const void *sendbuf, MPI_Aint i++; } - if (recv_dtp) { - mpi_errno = MPIR_Sched_cb(dtp_release_ref, recv_dtp, s); - MPIR_ERR_CHECK(mpi_errno); - } + mpi_errno = MPIR_Sched_cb(reset_shared_state, ss, s); + MPIR_ERR_CHECK(mpi_errno); fn_exit: return mpi_errno; diff --git a/src/mpi/coll/ialltoallw/ialltoallw_intra_sched_inplace.c b/src/mpi/coll/ialltoallw/ialltoallw_intra_sched_inplace.c index 2f17f07f78c..23bdca07055 100644 --- a/src/mpi/coll/ialltoallw/ialltoallw_intra_sched_inplace.c +++ b/src/mpi/coll/ialltoallw/ialltoallw_intra_sched_inplace.c @@ -65,7 +65,7 @@ int MPIR_Ialltoallw_intra_sched_inplace(const void *sendbuf, const MPI_Aint send else dst = i; - MPIR_Datatype_get_size_macro(recvtypes[i], recvtype_sz); + MPIR_Datatype_get_size_macro(recvtypes[dst], recvtype_sz); mpi_errno = MPIR_Sched_send(((char *) recvbuf + rdispls[dst]), recvcounts[dst], recvtypes[dst], dst, comm_ptr, s); MPIR_ERR_CHECK(mpi_errno); diff --git a/src/mpi/coll/ialltoallw/ialltoallw_tsp_inplace.c b/src/mpi/coll/ialltoallw/ialltoallw_tsp_inplace.c index d32a8ee1236..afdc7819c71 100644 --- a/src/mpi/coll/ialltoallw/ialltoallw_tsp_inplace.c +++ b/src/mpi/coll/ialltoallw/ialltoallw_tsp_inplace.c @@ -36,6 +36,10 @@ int MPIR_TSP_Ialltoallw_sched_intra_inplace(const void *sendbuf, const MPI_Aint mpi_errno = MPIR_Sched_next_tag(comm, &tag); MPIR_ERR_CHECK(mpi_errno); + /* FIXME: Here we allocate tmp_buf using extent and send/recv with datatype directly, + * which can be potentially very inefficient. Why don't we use bytes as in + * ialltoallw_intra_sched_inplace.c ? + */ MPI_Aint max_size; max_size = 0; for (i = 0; i < nranks; ++i) { diff --git a/src/mpi/init/mpir_init.c b/src/mpi/init/mpir_init.c index db14a588ad4..708c9daeb67 100644 --- a/src/mpi/init/mpir_init.c +++ b/src/mpi/init/mpir_init.c @@ -365,6 +365,10 @@ int MPII_Finalize(MPIR_Session * session_ptr) MPID_Thread_mutex_destroy(&session_ptr->mutex, &thr_err); MPIR_Assert(thr_err == 0); + if (session_ptr->errhandler != NULL) { + MPIR_Errhandler_free_impl(session_ptr->errhandler); + } + MPIR_Handle_obj_free(&MPIR_Session_mem, session_ptr); } diff --git a/src/mpi/request/request_impl.c b/src/mpi/request/request_impl.c index 92ef18ab47e..28ba2769e6f 100644 --- a/src/mpi/request/request_impl.c +++ b/src/mpi/request/request_impl.c @@ -22,7 +22,9 @@ MPIR_CVAR_REQUEST_ERR_FATAL is set to true, these routines will return the error code of the request immediately. The default MPI_ERRS_ARE_FATAL error handler will dump a error stack in this - case, which maybe more convenient for debugging. + case, which maybe more convenient for debugging. This cvar will also + make nonblocking shched return error right away as it issues + operations. === END_MPI_T_CVAR_INFO_BLOCK === */ diff --git a/src/mpid/ch4/shm/ipc/src/ipc_send.h b/src/mpid/ch4/shm/ipc/src/ipc_send.h index 0f4754711d4..acc078971fa 100644 --- a/src/mpid/ch4/shm/ipc/src/ipc_send.h +++ b/src/mpid/ch4/shm/ipc/src/ipc_send.h @@ -133,11 +133,9 @@ MPL_STATIC_INLINE_PREFIX int MPIDI_IPC_mpi_isend(const void *buf, MPI_Aint count int mpi_errno = MPI_SUCCESS; MPIR_FUNC_ENTER; - int context_offset = MPIR_PT2PT_ATTR_CONTEXT_OFFSET(attr); - bool done = false; mpi_errno = MPIDI_IPCI_try_lmt_isend(buf, count, datatype, rank, tag, comm, - context_offset, addr, request, &done); + attr, addr, request, &done); MPIR_ERR_CHECK(mpi_errno); if (!done) { diff --git a/src/mpid/ch4/src/ch4_vci.h b/src/mpid/ch4/src/ch4_vci.h index 64acb1f07e2..6fbff5f47d9 100644 --- a/src/mpid/ch4/src/ch4_vci.h +++ b/src/mpid/ch4/src/ch4_vci.h @@ -129,11 +129,9 @@ static bool is_vci_restricted_to_zero(MPIR_Comm * comm) if (!(comm->comm_kind == MPIR_COMM_KIND__INTRACOMM && !comm->tainted)) { vci_restricted |= true; } -#ifdef MPIDI_OFI_VNI_USE_DOMAIN if (!MPIDI_global.is_initialized) { vci_restricted |= true; } -#endif /* ifdef MPIDI_OFI_VNI_USE_DOMAIN */ return vci_restricted; } diff --git a/src/mpid/common/sched/mpidu_sched.c b/src/mpid/common/sched/mpidu_sched.c index 272e3d81d55..02cf12f5dce 100644 --- a/src/mpid/common/sched/mpidu_sched.c +++ b/src/mpid/common/sched/mpidu_sched.c @@ -251,6 +251,9 @@ static int MPIDU_Sched_start_entry(struct MPIDU_Sched *s, size_t idx, struct MPI e->status = MPIDU_SCHED_ENTRY_STATUS_FAILED; MPL_DBG_MSG_D(MPIR_DBG_COMM, VERBOSE, "Sched SEND failed. Errflag: %d\n", (int) r->u.nbc.errflag); + if (MPIR_CVAR_REQUEST_ERR_FATAL) { + return ret_errno; + } } else { e->status = MPIDU_SCHED_ENTRY_STATUS_STARTED; } @@ -274,6 +277,9 @@ static int MPIDU_Sched_start_entry(struct MPIDU_Sched *s, size_t idx, struct MPI e->status = MPIDU_SCHED_ENTRY_STATUS_STARTED; MPL_DBG_MSG_D(MPIR_DBG_COMM, VERBOSE, "Sched RECV failed. Errflag: %d\n", (int) r->u.nbc.errflag); + if (MPIR_CVAR_REQUEST_ERR_FATAL) { + return ret_errno; + } } else { e->status = MPIDU_SCHED_ENTRY_STATUS_STARTED; } @@ -284,6 +290,9 @@ static int MPIDU_Sched_start_entry(struct MPIDU_Sched *s, size_t idx, struct MPI MPIR_CONTEXT_INTRA_PT2PT, &e->u.send.sreq); if (unlikely(ret_errno)) { e->status = MPIDU_SCHED_ENTRY_STATUS_FAILED; + if (MPIR_CVAR_REQUEST_ERR_FATAL) { + return ret_errno; + } } else { e->status = MPIDU_SCHED_ENTRY_STATUS_STARTED; } @@ -294,6 +303,9 @@ static int MPIDU_Sched_start_entry(struct MPIDU_Sched *s, size_t idx, struct MPI MPIR_CONTEXT_INTRA_PT2PT, &e->u.recv.rreq); if (unlikely(ret_errno)) { e->status = MPIDU_SCHED_ENTRY_STATUS_FAILED; + if (MPIR_CVAR_REQUEST_ERR_FATAL) { + return ret_errno; + } } else { e->status = MPIDU_SCHED_ENTRY_STATUS_STARTED; } @@ -336,6 +348,9 @@ static int MPIDU_Sched_start_entry(struct MPIDU_Sched *s, size_t idx, struct MPI } } e->status = MPIDU_SCHED_ENTRY_STATUS_FAILED; + if (MPIR_CVAR_REQUEST_ERR_FATAL) { + return ret_errno; + } } else { e->status = MPIDU_SCHED_ENTRY_STATUS_COMPLETE; } @@ -356,6 +371,9 @@ static int MPIDU_Sched_start_entry(struct MPIDU_Sched *s, size_t idx, struct MPI } } e->status = MPIDU_SCHED_ENTRY_STATUS_FAILED; + if (MPIR_CVAR_REQUEST_ERR_FATAL) { + return ret_errno; + } } else { e->status = MPIDU_SCHED_ENTRY_STATUS_COMPLETE; } @@ -1177,10 +1195,10 @@ static int MPIDU_Sched_progress_state(struct MPIDU_Sched_state *state, int *made /* TODO refactor into a sched_complete routine? */ switch (s->req->u.nbc.errflag) { case MPIR_ERR_PROC_FAILED: - MPIR_ERR_SET(s->req->status.MPI_ERROR, MPIX_ERR_PROC_FAILED, "**comm"); + MPIR_ERR_SET(s->req->status.MPI_ERROR, MPIX_ERR_PROC_FAILED, "**proc_failed"); break; case MPIR_ERR_OTHER: - MPIR_ERR_SET(s->req->status.MPI_ERROR, MPI_ERR_OTHER, "**comm"); + MPIR_ERR_SET(s->req->status.MPI_ERROR, MPI_ERR_OTHER, "**other"); break; case MPIR_ERR_NONE: default: diff --git a/test/mpi/attr/keyval_double_free_type.c b/test/mpi/attr/keyval_double_free_type.c index 3e3ea1eb618..74e5a8908b8 100644 --- a/test/mpi/attr/keyval_double_free_type.c +++ b/test/mpi/attr/keyval_double_free_type.c @@ -10,8 +10,8 @@ /* tests multiple invocations of MPI_Type_free_keyval on the same keyval */ -int delete_fn(MPI_Comm comm, int keyval, void *attr, void *extra); -int delete_fn(MPI_Comm comm, int keyval, void *attr, void *extra) +int delete_fn(MPI_Datatype datatype, int keyval, void *attr, void *extra); +int delete_fn(MPI_Datatype datatype, int keyval, void *attr, void *extra) { MPI_Type_free_keyval(&keyval); return MPI_SUCCESS; diff --git a/test/mpi/attr/keyval_double_free_win.c b/test/mpi/attr/keyval_double_free_win.c index 3e88707fd86..85184957685 100644 --- a/test/mpi/attr/keyval_double_free_win.c +++ b/test/mpi/attr/keyval_double_free_win.c @@ -13,8 +13,8 @@ /* tests multiple invocations of MPI_Win_free_keyval on the same keyval */ -int delete_fn(MPI_Comm comm, int keyval, void *attr, void *extra); -int delete_fn(MPI_Comm comm, int keyval, void *attr, void *extra) +int delete_fn(MPI_Win win, int keyval, void *attr, void *extra); +int delete_fn(MPI_Win win, int keyval, void *attr, void *extra) { MPI_Win_free_keyval(&keyval); return MPI_SUCCESS; diff --git a/test/mpi/coll/alltoallw2.c b/test/mpi/coll/alltoallw2.c index adb3da3567f..529861abb02 100644 --- a/test/mpi/coll/alltoallw2.c +++ b/test/mpi/coll/alltoallw2.c @@ -23,125 +23,178 @@ that use point-to-point operations */ +static int test_noinplace(MPI_Comm comm); +static int test_inplace(MPI_Comm comm, bool sametype); + int main(int argc, char **argv) { - + int errs = 0; MPI_Comm comm; - int *sbuf, *rbuf; - int rank, size; - int *sendcounts, *recvcounts, *rdispls, *sdispls; - int i, j, *p, errs; - MPI_Datatype *sendtypes, *recvtypes; MTest_Init(&argc, &argv); - errs = 0; - while (MTestGetIntracommGeneral(&comm, 2, 1)) { if (comm == MPI_COMM_NULL) continue; - /* Create the buffer */ - MPI_Comm_size(comm, &size); - MPI_Comm_rank(comm, &rank); - sbuf = (int *) malloc(size * size * sizeof(int)); - rbuf = (int *) malloc(size * size * sizeof(int)); - if (!sbuf || !rbuf) { - fprintf(stderr, "Could not allocated buffers!\n"); - MPI_Abort(comm, 1); - } + errs += test_noinplace(comm); - /* Load up the buffers */ - for (i = 0; i < size * size; i++) { - sbuf[i] = i + 100 * rank; - rbuf[i] = -i; - } +#if MTEST_HAVE_MIN_MPI_VERSION(2,2) + errs += test_inplace(comm, true); + errs += test_inplace(comm, false); +#endif + MTestFreeComm(&comm); + } - /* Create and load the arguments to alltoallv */ - sendcounts = (int *) malloc(size * sizeof(int)); - recvcounts = (int *) malloc(size * sizeof(int)); - rdispls = (int *) malloc(size * sizeof(int)); - sdispls = (int *) malloc(size * sizeof(int)); - sendtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); - recvtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); - if (!sendcounts || !recvcounts || !rdispls || !sdispls || !sendtypes || !recvtypes) { - fprintf(stderr, "Could not allocate arg items!\n"); - MPI_Abort(comm, 1); - } - /* Note that process 0 sends no data (sendcounts[0] = 0) */ - for (i = 0; i < size; i++) { - sendcounts[i] = i; - recvcounts[i] = rank; - rdispls[i] = i * rank * sizeof(int); - sdispls[i] = (((i + 1) * (i)) / 2) * sizeof(int); - sendtypes[i] = recvtypes[i] = MPI_INT; - } - MPI_Alltoallw(sbuf, sendcounts, sdispls, sendtypes, - rbuf, recvcounts, rdispls, recvtypes, comm); - - /* Check rbuf */ - for (i = 0; i < size; i++) { - p = rbuf + rdispls[i] / sizeof(int); - for (j = 0; j < rank; j++) { - if (p[j] != i * 100 + (rank * (rank + 1)) / 2 + j) { - fprintf(stderr, "[%d] got %d expected %d for %dth\n", - rank, p[j], (i * (i + 1)) / 2 + j, j); - errs++; - } + MTest_Finalize(errs); + return MTestReturnValue(errs); +} + +static int test_noinplace(MPI_Comm comm) +{ + int errs = 0; + int *sbuf, *rbuf; + int *sendcounts, *recvcounts, *rdispls, *sdispls; + MPI_Datatype *sendtypes, *recvtypes; + + int rank, size; + MPI_Comm_size(comm, &size); + MPI_Comm_rank(comm, &rank); + + /* Create the buffer */ + sbuf = (int *) malloc(size * size * sizeof(int)); + rbuf = (int *) malloc(size * size * sizeof(int)); + if (!sbuf || !rbuf) { + fprintf(stderr, "Could not allocated buffers!\n"); + MPI_Abort(comm, 1); + } + + /* Load up the buffers */ + for (int i = 0; i < size * size; i++) { + sbuf[i] = i + 100 * rank; + rbuf[i] = -i; + } + + /* Create and load the arguments to alltoallv */ + sendcounts = (int *) malloc(size * sizeof(int)); + recvcounts = (int *) malloc(size * sizeof(int)); + rdispls = (int *) malloc(size * sizeof(int)); + sdispls = (int *) malloc(size * sizeof(int)); + sendtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); + recvtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); + if (!sendcounts || !recvcounts || !rdispls || !sdispls || !sendtypes || !recvtypes) { + fprintf(stderr, "Could not allocate arg items!\n"); + MPI_Abort(comm, 1); + } + /* Note that process 0 sends no data (sendcounts[0] = 0) */ + for (int i = 0; i < size; i++) { + sendcounts[i] = i; + recvcounts[i] = rank; + rdispls[i] = i * rank * sizeof(int); + sdispls[i] = (((i + 1) * (i)) / 2) * sizeof(int); + sendtypes[i] = recvtypes[i] = MPI_INT; + } + MPI_Alltoallw(sbuf, sendcounts, sdispls, sendtypes, rbuf, recvcounts, rdispls, recvtypes, comm); + + /* Check rbuf */ + for (int i = 0; i < size; i++) { + int *p = rbuf + rdispls[i] / sizeof(int); + for (int j = 0; j < rank; j++) { + if (p[j] != i * 100 + (rank * (rank + 1)) / 2 + j) { + fprintf(stderr, "[%d] got %d expected %d for %dth\n", + rank, p[j], (i * (i + 1)) / 2 + j, j); + errs++; } } + } + + free(sendtypes); + free(sdispls); + free(sendcounts); + free(sbuf); + free(recvtypes); + free(rdispls); + free(recvcounts); + free(rbuf); - free(sendtypes); - free(sdispls); - free(sendcounts); - free(sbuf); + return errs; +} #if MTEST_HAVE_MIN_MPI_VERSION(2,2) - /* check MPI_IN_PLACE, added in MPI-2.2 */ - free(rbuf); - rbuf = (int *) malloc(size * (2 * size) * sizeof(int)); - if (!rbuf) { - fprintf(stderr, "Could not reallocate rbuf!\n"); - MPI_Abort(comm, 1); +static int test_inplace(MPI_Comm comm, bool sametype) +{ + int errs = 0; + int *rbuf; + int *recvcounts, *rdispls; + MPI_Datatype *recvtypes; + + int rank, size; + MPI_Comm_size(comm, &size); + MPI_Comm_rank(comm, &rank); + + /* Create the buffer */ + rbuf = (int *) malloc(size * (2 * size) * sizeof(int)); + if (!rbuf) { + fprintf(stderr, "Could not reallocate rbuf!\n"); + MPI_Abort(comm, 1); + } + + /* Load up the buffers */ + memset(rbuf, -1, size * (2 * size) * sizeof(int)); + for (int i = 0; i < size; i++) { + int *p = rbuf + i * (2 * size); + for (int j = 0; j < i + rank; ++j) { + p[j] = 100 * rank + 10 * i + j; } + } - /* Load up the buffers */ - for (i = 0; i < size; i++) { - /* alltoallw displs are in bytes, not in type extents */ - rdispls[i] = i * (2 * size) * sizeof(int); + /* Create and load the arguments to alltoallv */ + recvcounts = (int *) malloc(size * sizeof(int)); + rdispls = (int *) malloc(size * sizeof(int)); + recvtypes = (MPI_Datatype *) malloc(size * sizeof(MPI_Datatype)); + if (!recvcounts || !rdispls || !recvtypes) { + fprintf(stderr, "Could not allocate arg items!\n"); + MPI_Abort(comm, 1); + } + + for (int i = 0; i < size; i++) { + /* alltoallw displs are in bytes, not in type extents */ + rdispls[i] = i * (2 * size) * sizeof(int); + if (sametype) { recvtypes[i] = MPI_INT; recvcounts[i] = i + rank; + } else { + MPI_Type_contiguous(i + rank, MPI_INT, &recvtypes[i]); + MPI_Type_commit(&recvtypes[i]); + recvcounts[i] = 1; } - memset(rbuf, -1, size * (2 * size) * sizeof(int)); - for (i = 0; i < size; i++) { - p = rbuf + (rdispls[i] / sizeof(int)); - for (j = 0; j < recvcounts[i]; ++j) { - p[j] = 100 * rank + 10 * i + j; - } + } + + MPI_Alltoallw(MPI_IN_PLACE, NULL, NULL, NULL, rbuf, recvcounts, rdispls, recvtypes, comm); + + if (!sametype) { + for (int i = 0; i < size; i++) { + MPI_Type_free(&recvtypes[i]); } + } - MPI_Alltoallw(MPI_IN_PLACE, NULL, NULL, NULL, rbuf, recvcounts, rdispls, recvtypes, comm); - - /* Check rbuf */ - for (i = 0; i < size; i++) { - p = rbuf + (rdispls[i] / sizeof(int)); - for (j = 0; j < recvcounts[i]; j++) { - int expected = 100 * i + 10 * rank + j; - if (p[j] != expected) { - fprintf(stderr, "[%d] got %d expected %d for block=%d, element=%dth\n", - rank, p[j], expected, i, j); - ++errs; - } + /* Check rbuf */ + for (int i = 0; i < size; i++) { + int *p = rbuf + (rdispls[i] / sizeof(int)); + for (int j = 0; j < i + rank; j++) { + int expected = 100 * i + 10 * rank + j; + if (p[j] != expected) { + fprintf(stderr, "[%d] got %d expected %d for block=%d, element=%dth\n", + rank, p[j], expected, i, j); + ++errs; } } -#endif - - free(recvtypes); - free(rdispls); - free(recvcounts); - free(rbuf); - MTestFreeComm(&comm); } - MTest_Finalize(errs); - return MTestReturnValue(errs); + free(recvtypes); + free(rdispls); + free(recvcounts); + free(rbuf); + + return errs; } +#endif diff --git a/test/mpi/coll/nonblocking2.c b/test/mpi/coll/nonblocking2.c index 615d3082efc..d05e39be6d0 100644 --- a/test/mpi/coll/nonblocking2.c +++ b/test/mpi/coll/nonblocking2.c @@ -58,8 +58,8 @@ int *sendcounts = NULL; int *recvcounts = NULL; int *sdispls = NULL; int *rdispls = NULL; -int *sendtypes = NULL; -int *recvtypes = NULL; +MPI_Datatype *sendtypes = NULL; +MPI_Datatype *recvtypes = NULL; signed char *buf_alias = NULL; MPI_Request req; diff --git a/test/mpi/coll/nonblocking3.c b/test/mpi/coll/nonblocking3.c index 52e20a034c4..ab652569f0f 100644 --- a/test/mpi/coll/nonblocking3.c +++ b/test/mpi/coll/nonblocking3.c @@ -95,8 +95,8 @@ struct laundry { int *recvcounts; int *sdispls; int *rdispls; - int *sendtypes; - int *recvtypes; + MPI_Datatype *sendtypes; + MPI_Datatype *recvtypes; }; static void cleanup_laundry(struct laundry *l) @@ -136,8 +136,8 @@ static void start_random_nonblocking(MPI_Comm comm, unsigned int rndnum, MPI_Req int *recvcounts = NULL; int *sdispls = NULL; int *rdispls = NULL; - int *sendtypes = NULL; - int *recvtypes = NULL; + MPI_Datatype *sendtypes = NULL; + MPI_Datatype *recvtypes = NULL; signed char *buf_alias = NULL; MPI_Comm_rank(comm, &rank); diff --git a/test/mpi/configure.ac b/test/mpi/configure.ac index f30266467a1..e8c0c9eb713 100644 --- a/test/mpi/configure.ac +++ b/test/mpi/configure.ac @@ -471,6 +471,11 @@ if test "$MPI_IS_MPICH" = "yes" ; then fi fi +AM_CONDITIONAL([NOT_STRICTMPI], [test x$enable_strictmpi = xno]) +if test "$enable_strictmpi" = "yes" ; then + AC_DEFINE([ENABLE_STRICTMPI], [1], [Define if configured with --enable-strictmpi]) +fi + # First, determine whether we are/can support the language bindings # # Since F90/F90FLAGS are replaced by FC/FCFLAGS, rather than silently diff --git a/test/mpi/datatype/Makefile.am b/test/mpi/datatype/Makefile.am index 1c4eb6876d6..8ec4a69f6df 100644 --- a/test/mpi/datatype/Makefile.am +++ b/test/mpi/datatype/Makefile.am @@ -31,14 +31,12 @@ noinst_PROGRAMS = \ hindexed_block_contents \ hvecblklen \ indexed_misc \ - indexed_misc_oldapi \ large_count \ large_type \ large_type_sendrec \ large_vec \ type_large \ lbub \ - lbub_oldapi \ localpack \ longdouble \ lots_of_types \ @@ -53,14 +51,12 @@ noinst_PROGRAMS = \ simple_pack_external2 \ simple_resized \ simple_size_extent \ - simple_size_extent_oldapi \ sizedtypes \ slice_pack \ slice_pack_external \ struct_derived_zeros \ struct_empty_el \ struct_ezhov \ - struct_no_real_types \ struct_pack \ structpack2 \ struct_pack_mpi_bottom \ @@ -72,7 +68,6 @@ noinst_PROGRAMS = \ tfree \ tmatchsize \ transpose_pack \ - transpose_pack_oldapi \ tresized \ tresized2 \ triangular_pack \ @@ -80,13 +75,22 @@ noinst_PROGRAMS = \ typefree \ typelb \ typename \ - typename_oldapi \ unpack \ unusual_noncontigs \ vecblklen \ zeroblks \ zeroparms +if NOT_STRICTMPI +noinst_PROGRAMS += \ + indexed_misc_oldapi \ + lbub_oldapi \ + simple_size_extent_oldapi \ + struct_no_real_types \ + transpose_pack_oldapi \ + typename_oldapi +endif + # Some of the tests use a more comprehensive set of datatype tests. # These must specify a different LDADD that includes the object file # with these additional routines diff --git a/test/mpi/datatype/typename.c b/test/mpi/datatype/typename.c index c8544ca9fb8..17bfe4c6fe6 100644 --- a/test/mpi/datatype/typename.c +++ b/test/mpi/datatype/typename.c @@ -156,8 +156,14 @@ int main(int argc, char **argv) isSynonymName = 0; for (i = 0; mpi_names[i].name != 0; i++) { /* Are we in the optional types? */ - if (strcmp(mpi_names[i].name, "MPI_REAL4") == 0) + if (strcmp(mpi_names[i].name, "MPI_REAL4") == 0) { inOptional = 1; +#ifdef ENABLE_STRICTMPI + /* strictly we can't use MPI_DATATYPE_NULL to test datatype availability, + * just skip the optional datatypes */ + break; +#endif + } /* If this optional type is not supported, skip it */ if (inOptional && mpi_names[i].dtype == MPI_DATATYPE_NULL) continue; diff --git a/test/mpi/errhan/Makefile.am b/test/mpi/errhan/Makefile.am index 0cab7605d35..25f775909b8 100644 --- a/test/mpi/errhan/Makefile.am +++ b/test/mpi/errhan/Makefile.am @@ -15,12 +15,16 @@ EXTRA_DIST = testlist noinst_PROGRAMS = \ adderr \ commcall \ - commcall_oldapi \ errfatal \ predef_eh \ errstring2 \ dynamic_errcode_predefined_errclass +if NOT_STRICTMPI +noinst_PROGRAMS += \ + commcall_oldapi +endif + EXTRA_PROGRAMS = errcode errring errstring errcode_SOURCES = errcode.c errmsg.c diff --git a/test/mpi/errors/datatype/Makefile.am b/test/mpi/errors/datatype/Makefile.am index 888d67a65ca..85392441790 100644 --- a/test/mpi/errors/datatype/Makefile.am +++ b/test/mpi/errors/datatype/Makefile.am @@ -12,12 +12,16 @@ EXTRA_DIST = testlist ## correctly noinst_PROGRAMS = getcnterr \ type_contiguous_nullarg \ - type_extent_nullarg \ type_get_extent_nullarg \ type_get_true_extent_nullarg \ type_get_true_extent_x_nullarg \ - type_lb_nullarg \ - type_ub_nullarg \ type_size_x_nullarg \ type_vector_nullarg +if NOT_STRICTMPI +noinst_PROGRAMS += \ + type_extent_nullarg \ + type_lb_nullarg \ + type_ub_nullarg +endif + diff --git a/test/mpi/impls/mpich/comm/stream_comm_dup.c b/test/mpi/impls/mpich/comm/stream_comm_dup.c index 3ec2de05f50..09d228dce56 100644 --- a/test/mpi/impls/mpich/comm/stream_comm_dup.c +++ b/test/mpi/impls/mpich/comm/stream_comm_dup.c @@ -73,7 +73,7 @@ static int test_stream_comm_dup_single(MPIX_Stream stream) MPIX_Comm_get_stream(dup_comm, 0, &stream_check); if (stream_check != stream) { - printf("MPIX_Comm_get_stream did not return expected stread\n"); + printf("MPIX_Comm_get_stream did not return expected stream\n"); errs++; } @@ -108,7 +108,7 @@ static int test_stream_comm_idup_multiplex(MPIX_Stream stream) for (int i = 0; i < 2; i++) { MPIX_Comm_get_stream(dup_comm, i, &stream_check); if (stream_check != local_streams[i]) { - printf("MPIX_Comm_get_stream (idx=%d) did not return expected stread\n", i); + printf("MPIX_Comm_get_stream (idx=%d) did not return expected stream\n", i); errs++; } }