Below are two ways of writing what is seemingly (to me at least) exactly the same thing:
void do_some_work(MPI_Request* send_reqs, int* send_counter) {
for (int i = 0; i < someNumber; ++i) {
// working version
MPI_Request req = send_reqs[*send_counter];
MPI_Isend(ptr, n_elem, M_MPI_REAL, trg_rank, tag, MPI_COMM_WORLD, &req);
// buggy version...
MPI_Request* req = &send_reqs[*send_counter];
MPI_Isend(ptr, n_elem, M_MPI_REAL, trg_rank, tag, MPI_COMM_WORLD, req);
// increment the counter
(*send_counter)++;
}
}
// [...]
// Allocate the request array & start the sends
MPI_Request* send_reqs = (MPI_Request*)calloc(someNumber, sizeof(MPI_Request));
int send_counter = 0;
do_some_work(send_reqs, &send_counter);
// [...]
// later on, at the sync step:
MPI_Waitall(send_counter, send_reqs, MPI_STATUSES_IGNORE);
However, in practice, the second one triggers random memory access errors (it has exactly the same symptoms as if MPI were writing random stuff all over the place, sometimes triggering segmentation faults or simply modifying values it shouldn't). To add to the weirdness of the issue, the code below works for 3 MPI ranks or less and starts acting out for 4 or 5 ranks (didn't test with more ranks).
Does anyone have any idea or explanation as to what changes and why one works while the other does not ?
MPI_Waitfunction. – Victor Eijkhout Feb 20 '24 at 12:50MPI_Waitallon all the posted send/recv though – Gilles Poncelet Feb 20 '24 at 12:58reqis its own object, which is initialized by copy in the first line. You put the request intoreq, but you later wait on the element insend_reqs, which is not the same object. The second way you show avoids this problem. – Wolfgang Bangerth Feb 20 '24 at 13:51send_counteris used as an integer in the last line, but apparently as a pointer in indexing intosend_reqs. I think you need to show a complete piece of code. – Wolfgang Bangerth Feb 20 '24 at 13:52