15#if defined(__parallel)
16static bool mpi_initialized_by_cp2k =
false;
17static bool mpi_attached_by_cp2k =
false;
25 const int error = (CMD); \
26 if (MPI_SUCCESS != error) { \
27 fprintf(stderr, "MPI error #%i in %s:%i\n", error, __FILE__, __LINE__); \
28 MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); \
35static void assert_outside_parallel(
const char *routine_name) {
36 if (omp_in_parallel()) {
37 fprintf(stderr,
"%s must be called outside an OpenMP parallel region.\n",
46static const char *thread_level_name(
const int level) {
48 case MPI_THREAD_SINGLE:
49 return "MPI_THREAD_SINGLE";
50 case MPI_THREAD_FUNNELED:
51 return "MPI_THREAD_FUNNELED";
52 case MPI_THREAD_SERIALIZED:
53 return "MPI_THREAD_SERIALIZED";
54 case MPI_THREAD_MULTIPLE:
55 return "MPI_THREAD_MULTIPLE";
64static void require_thread_multiple(
const int provided) {
65 if (provided < MPI_THREAD_MULTIPLE) {
66 fprintf(stderr,
"CP2K requires MPI_THREAD_MULTIPLE, but MPI provides %s.\n",
67 thread_level_name(provided));
68 MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
79#if defined(__parallel)
80 assert_outside_parallel(
"cp_mpi_init");
81 if (mpi_attached_by_cp2k) {
82 fprintf(stderr,
"cp_mpi_init must only be called once per lifecycle.\n");
86 int finalized, initialized, provided;
87 CHECK(MPI_Finalized(&finalized));
89 fprintf(stderr,
"cp_mpi_init cannot be called after MPI_Finalize.\n");
93 CHECK(MPI_Initialized(&initialized));
95 CHECK(MPI_Query_thread(&provided));
97 CHECK(MPI_Init_thread(argc, argv, MPI_THREAD_MULTIPLE, &provided));
98 mpi_initialized_by_cp2k =
true;
100 require_thread_multiple(provided);
101 mpi_attached_by_cp2k =
true;
113#if defined(__parallel)
114 assert_outside_parallel(
"cp_mpi_finalize");
115 if (!mpi_attached_by_cp2k) {
116 fprintf(stderr,
"cp_mpi_finalize called without a matching cp_mpi_init.\n");
121 CHECK(MPI_Finalized(&finalized));
123 fprintf(stderr,
"MPI was finalized before cp_mpi_finalize.\n");
126 if (mpi_initialized_by_cp2k) {
127 CHECK(MPI_Finalize());
128 mpi_initialized_by_cp2k =
false;
130 mpi_attached_by_cp2k =
false;
139#if defined(__parallel)
140 return MPI_COMM_WORLD;
151#if defined(__parallel)
153 return 0 != fortran_comm ? MPI_Comm_f2c(fortran_comm) : MPI_COMM_NULL;
165#if defined(__parallel)
166 return MPI_Comm_c2f(comm);
178#if defined(__parallel)
180 if (MPI_COMM_NULL != comm) {
181 CHECK(MPI_Comm_rank(comm, &rank));
195#if defined(__parallel)
197 if (MPI_COMM_NULL != comm) {
198 CHECK(MPI_Comm_size(comm, &nranks));
211#if defined(__parallel)
212 if (MPI_COMM_NULL != comm) {
213 CHECK(MPI_Barrier(comm));
225#if defined(__parallel)
226 CHECK(MPI_Dims_create(nnodes, ndims, dims));
229 for (
int i = 1;
i < ndims;
i++) {
240 const int dims[],
const int periods[],
242#if defined(__parallel)
243 assert_outside_parallel(
"cp_mpi_cart_create");
245 CHECK(MPI_Cart_create(comm_old, ndims, dims, periods, reorder, &comm_cart));
262 int periods[],
int coords[]) {
263#if defined(__parallel)
264 CHECK(MPI_Cart_get(comm, maxdims, dims, periods, coords));
267 for (
int i = 0;
i < maxdims;
i++) {
280#if defined(__parallel)
282 CHECK(MPI_Cart_rank(comm, coords, &rank));
296 const int remain_dims[]) {
297#if defined(__parallel)
298 assert_outside_parallel(
"cp_mpi_cart_sub");
300 CHECK(MPI_Cart_sub(comm, remain_dims, &newcomm));
314#if defined(__parallel)
315 assert_outside_parallel(
"cp_mpi_comm_free");
316 CHECK(MPI_Comm_free(comm));
328#if defined(__parallel)
330 CHECK(MPI_Comm_compare(comm1, comm2, &res));
331 return res == MPI_IDENT || res == MPI_CONGRUENT || res == MPI_SIMILAR;
344#if defined(__parallel)
345 if (MPI_COMM_NULL != comm) {
349 CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_MAX, comm));
350 memcpy(values, recvbuf, count *
sizeof(
int));
368#if defined(__parallel)
369 if (MPI_COMM_NULL != comm) {
373 CHECK(MPI_Allreduce(values, recvbuf, count, MPI_UINT64_T, MPI_MAX, comm));
374 memcpy(values, recvbuf, count *
sizeof(uint64_t));
392#if defined(__parallel)
393 if (MPI_COMM_NULL != comm) {
397 CHECK(MPI_Allreduce(values, recvbuf, count, MPI_DOUBLE, MPI_MAX, comm));
398 memcpy(values, recvbuf, count *
sizeof(
double));
415#if defined(__parallel)
416 if (MPI_COMM_NULL != comm) {
420 CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_SUM, comm));
421 memcpy(values, recvbuf, count *
sizeof(
int));
438#if defined(__parallel)
439 if (MPI_COMM_NULL != comm) {
443 CHECK(MPI_Allreduce(values, recvbuf, count, MPI_LONG, MPI_SUM, comm));
444 memcpy(values, recvbuf, count *
sizeof(
long));
462#if defined(__parallel)
463 if (MPI_COMM_NULL != comm) {
467 CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT64_T, MPI_SUM, comm));
468 memcpy(values, recvbuf, count *
sizeof(int64_t));
486#if defined(__parallel)
487 if (MPI_COMM_NULL != comm) {
491 CHECK(MPI_Allreduce(values, recvbuf, count, MPI_DOUBLE, MPI_SUM, comm));
492 memcpy(values, recvbuf, count *
sizeof(
double));
509 const int dest,
const int sendtag,
void *recvbuf,
510 const int recvcount,
const int source,
512#if defined(__parallel)
514 CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_BYTE, dest, sendtag, recvbuf,
515 recvcount, MPI_BYTE, source, recvtag, comm, &status));
516 int count_received = 0;
517 CHECK(MPI_Get_count(&status, MPI_BYTE, &count_received));
518 return count_received;
529 fprintf(stderr,
"Error: cp_mpi_sendrecv_byte not available without MPI\n");
539 const int dest,
const int sendtag,
double *recvbuf,
540 const int recvcount,
const int source,
542#if defined(__parallel)
544 CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_DOUBLE, dest, sendtag, recvbuf,
545 recvcount, MPI_DOUBLE, source, recvtag, comm, &status));
547 CHECK(MPI_Get_count(&status, MPI_DOUBLE, &count_received));
548 return count_received;
559 fprintf(stderr,
"Error: cp_mpi_sendrecv_double not available without MPI\n");
570#if defined(__parallel)
571 CHECK(MPI_Alltoall(sendbuf, sendcount, MPI_INT, recvbuf, recvcount, MPI_INT,
575 assert(sendcount == recvcount);
576 memcpy(recvbuf, sendbuf, sendcount *
sizeof(
int));
585 const int *sdispls,
void *recvbuf,
586 const int *recvcounts,
const int *rdispls,
588#if defined(__parallel)
589 CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_BYTE, recvbuf,
590 recvcounts, rdispls, MPI_BYTE, comm));
593 assert(sendcounts[0] == recvcounts[0]);
594 assert(sdispls[0] == 0 && rdispls[0] == 0);
595 memcpy(recvbuf, sendbuf, sendcounts[0]);
604 const int *sdispls,
double *recvbuf,
605 const int *recvcounts,
const int *rdispls,
607#if defined(__parallel)
608 CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_DOUBLE, recvbuf,
609 recvcounts, rdispls, MPI_DOUBLE, comm));
612 assert(sendcounts[0] == recvcounts[0]);
613 assert(sdispls[0] == 0 && rdispls[0] == 0);
614 memcpy(recvbuf, sendbuf, sendcounts[0] *
sizeof(
double));
624#if DBM_ALLOC_MPI && defined(__parallel)
625 CHECK(MPI_Alloc_mem((MPI_Aint)size, MPI_INFO_NULL, &result));
626#elif DBM_ALLOC_OPENMP && (201811 <= _OPENMP)
627 result = omp_alloc(size, omp_null_allocator);
629 result = malloc(size);
639#if DBM_ALLOC_MPI && defined(__parallel)
640 CHECK(MPI_Free_mem(mem));
641#elif DBM_ALLOC_OPENMP && (201811 <= _OPENMP)
642 omp_free(mem, omp_null_allocator);
int cp_mpi_comm_size(const cp_mpi_comm_t comm)
Wrapper around MPI_Comm_size.
void cp_mpi_free_mem(void *mem)
Wrapper around MPI_Free_mem.
void cp_mpi_max_int(int *values, const int count, const cp_mpi_comm_t comm)
Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_INT.
void cp_mpi_sum_double(double *values, const int count, const cp_mpi_comm_t comm)
Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_DOUBLE.
cp_mpi_comm_t cp_mpi_cart_create(const cp_mpi_comm_t comm_old, const int ndims, const int dims[], const int periods[], const int reorder)
Wrapper around MPI_Cart_create.
int cp_mpi_sendrecv_byte(const void *sendbuf, const int sendcount, const int dest, const int sendtag, void *recvbuf, const int recvcount, const int source, const int recvtag, const cp_mpi_comm_t comm)
Wrapper around MPI_Sendrecv for datatype MPI_BYTE.
void cp_mpi_alltoallv_double(const double *sendbuf, const int *sendcounts, const int *sdispls, double *recvbuf, const int *recvcounts, const int *rdispls, const cp_mpi_comm_t comm)
Wrapper around MPI_Alltoallv for datatype MPI_DOUBLE.
int cp_mpi_cart_rank(const cp_mpi_comm_t comm, const int coords[])
Wrapper around MPI_Cart_rank.
void cp_mpi_init(int *argc, char ***argv)
Initialize MPI with MPI_THREAD_MULTIPLE or attach to an active MPI.
int cp_mpi_comm_c2f(const cp_mpi_comm_t comm)
Wrapper around MPI_Comm_c2f.
void * cp_mpi_alloc_mem(size_t size)
Wrapper around MPI_Alloc_mem.
void cp_mpi_barrier(const cp_mpi_comm_t comm)
Wrapper around MPI_Barrier; a null communicator is a no-op.
void cp_mpi_max_uint64(uint64_t *values, const int count, const cp_mpi_comm_t comm)
Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_UINT64_T.
cp_mpi_comm_t cp_mpi_get_comm_world(void)
Returns MPI_COMM_WORLD.
void cp_mpi_cart_get(const cp_mpi_comm_t comm, int maxdims, int dims[], int periods[], int coords[])
Wrapper around MPI_Cart_get.
void cp_mpi_max_double(double *values, const int count, const cp_mpi_comm_t comm)
Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_DOUBLE.
void cp_mpi_sum_int64(int64_t *values, const int count, const cp_mpi_comm_t comm)
Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT64_T.
void cp_mpi_comm_free(cp_mpi_comm_t *comm)
Wrapper around MPI_Comm_free.
void cp_mpi_alltoall_int(const int *sendbuf, const int sendcount, int *recvbuf, const int recvcount, const cp_mpi_comm_t comm)
Wrapper around MPI_Alltoall for datatype MPI_INT.
void cp_mpi_dims_create(const int nnodes, const int ndims, int dims[])
Wrapper around MPI_Dims_create.
bool cp_mpi_comms_are_similar(const cp_mpi_comm_t comm1, const cp_mpi_comm_t comm2)
Wrapper around MPI_Comm_compare.
void cp_mpi_sum_int(int *values, const int count, const cp_mpi_comm_t comm)
Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT.
void cp_mpi_sum_long(long *values, const int count, const cp_mpi_comm_t comm)
Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_LONG.
void cp_mpi_alltoallv_byte(const void *sendbuf, const int *sendcounts, const int *sdispls, void *recvbuf, const int *recvcounts, const int *rdispls, const cp_mpi_comm_t comm)
Wrapper around MPI_Alltoallv for datatype MPI_BYTE.
void cp_mpi_finalize(void)
Detach from MPI and finalize it only if cp_mpi_init initialized it.
cp_mpi_comm_t cp_mpi_comm_f2c(const int fortran_comm)
Wrapper around MPI_Comm_f2c.
cp_mpi_comm_t cp_mpi_cart_sub(const cp_mpi_comm_t comm, const int remain_dims[])
Wrapper around MPI_Cart_sub.
int cp_mpi_sendrecv_double(const double *sendbuf, const int sendcount, const int dest, const int sendtag, double *recvbuf, const int recvcount, const int source, const int recvtag, const cp_mpi_comm_t comm)
Wrapper around MPI_Sendrecv for datatype MPI_DOUBLE.
int cp_mpi_comm_rank(const cp_mpi_comm_t comm)
Wrapper around MPI_Comm_rank.
static void const int const int i