<div dir="ltr">Dear MPICH community,<div><br></div><div>I am currently developing an event system built upon MPI and I have a few questions about the current state of multi-thread support from MPICH in the <i>MPI_THREAD_MULTIPLE</i> mode.</div><div><br></div><div><b>Question 1</b>. I am aware of the message envelope tuples (source, destination, tag, communicator) that may be used to identify and filter different messages. While using MPICH, can I rely on such information in order to guarantee that the correct messages will reach/be matched with their destinations in a multiprocess multithreaded program? I know this is quite a broad question, but I am more interested in the analysis of the following scenarios.</div><div><br></div><div><ul><li>Two threads in a process A want to send different messages to two different processes, B and C (each with one thread), while using the <b>same</b> <b>communicator</b> <b>and</b> <b>tag</b>. Code example:</li></ul><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">  // One process with N threads to N process with one thread (same tag)<br>  if (rank == 0) {<br>    std::thread t1([&]() { <br>      // Generate data ...<br>      MPI_Send(data, 1, MPI_CHAR, 1, 0, MPI_COMM_WORLD);<br>    });<br>    std::thread t2([&]() { <br>      // Generate data ...<br>      MPI_Send(data, 1, MPI_CHAR, 2, 0, MPI_COMM_WORLD);<br>    });<br>    t1.join(); t2.join();<br>  } else {<br>    MPI_Recv(data, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);<br>  }<br></blockquote><div><ul><li>The same scenario as above, but now each thread uses a <b>different tag</b> to communicate to their respective process while only sharing the <b>same</b> <b>communicator</b>. Code example:</li></ul></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">  // One process with N threads to N process with one thread (different tags)<br>  if (rank == 0) {<br>    std::thread t1([&]() { <br>      // Generate data ...<br>      MPI_Send(data, 1, MPI_CHAR, 1, 1, MPI_COMM_WORLD);<br>    });<br>    std::thread t2([&]() { <br>      // Generate data ...<br>      MPI_Send(data, 1, MPI_CHAR, 2, 2, MPI_COMM_WORLD);<br>    });<br>    t1.join(); t2.join();<br>  } else {<br>    MPI_Recv(data, 1, MPI_CHAR, 0, rank, MPI_COMM_WORLD, MPI_STATUS_IGNORE);<br>  }<b><br></b></blockquote><ul><li>Multiple threads from a process A want each to send a message to the same thread of another process B using the <b>same communicator and</b> <b>tag</b>. Code example:</li></ul><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">  // One process with N threads to one process with one thread (same tags)<br>  if (rank == 0) {<br>    std::thread t1([&]() {<br>      // Generate data ...<br>      MPI_Send(data, 1, MPI_CHAR, 1, 0, MPI_COMM_WORLD);<br>    });<br>    std::thread t2([&]() { <br>      // Generate data ...<br>      MPI_Send(data, 1, MPI_CHAR, 1, 0, MPI_COMM_WORLD);<br>    });<br>    t1.join(); t2.join();<br>  } else if (rank == 1) {<br>    MPI_Recv(data, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);<br>    // Process data ...<br>    MPI_Recv(data, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);<br>    // Process data ...<br>  }<br></blockquote><ul><li>One thread from a process A wants to send a message to one of multiple threads from a process B using the <b>same communicator and tag</b>. Code example:</li></ul><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">  // One process with one thread to one process with N threads (same tags)<br>  if (rank == 0) {<br>    MPI_Request requests[2];<br>    // Generate data ...<br>    MPI_Isend(data, 1, MPI_CHAR, 1, 0, MPI_COMM_WORLD, &requests[0]);<br>    // Generate data ...<br>    MPI_Isend(data, 1, MPI_CHAR, 1, 0, MPI_COMM_WORLD, &requests[1]);<br><br>    MPI_Waitall(2, requests, MPI_STATUSES_IGNORE);<br>  } else if (rank == 1) {<br>    std::thread t1([&]() {<br>      MPI_Recv(data, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);<br>      // Process data ...<br>    });<br>    std::thread t2([&]() {<br>      MPI_Recv(data, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);<br>      // Process data ...<br>    });<br>    t1.join(); t2.join();<br>  }<br></blockquote></div><div><ul><li>Two threads from a process A want each to send a message to two threads from a process B using different tags for each pair of threads (e.g. the pair A.1/B.1 uses a different tag from pair A.2/B.2). Code example:</li></ul></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">  // One process with N threads to one process with N thread (different tags)<br>  if (rank == 0) {<br>    std::thread t1([&]() {<br>      // Generate data ...<br>      MPI_Send(data, 1, MPI_CHAR, 1, 1, MPI_COMM_WORLD);<br>    });<br>    std::thread t2([&]() { <br>      // Generate data ...<br>      MPI_Send(data, 1, MPI_CHAR, 1, 2, MPI_COMM_WORLD);<br>    });<br>    t1.join(); t2.join();<br>  } else if (rank == 1) {<br>    std::thread t1([&]() {<br>      MPI_Recv(data, 1, MPI_CHAR, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);<br>      // Process data ...<br>    });<br>    std::thread t2([&]() {<br>      MPI_Recv(data, 1, MPI_CHAR, 0, 2, MPI_COMM_WORLD, MPI_STATUS_IGNORE);<br>      // Process data ...<br>    });<br>    t1.join(); t2.join();<br>  }<br></blockquote><div><br></div><div><b>Question 2</b>. Is there a problem when mixing blocking and non-blocking calls on opposite sides of a message? Even in the multithreaded scenarios described previously? (e.g. matching a <i style="">MPI_Isend</i> with a <i style="">MPI_Recv</i>, and vice-versa.)</div><div><br></div><div>Thank you.</div><div><br></div><div>Regards,</div><div>Guilherme Valarini</div><div><br></div><div><br></div></div>