在阅读了一些MPI规范之后,我首先要了解的是,在使用MPI_THREAD_SERIALIZED进行初始化时,程序必须确保在单独的线程中发生的MPI_Send / Recv调用不得重叠。换句话说,您需要一个互斥锁来保护MPI呼叫。
考虑这种情况:
Mutex mpi_lock = MUTEX_INITIALIZER;
void thread1_function(){
while(true){
/* things happen */
lock(mpi_lock);
MPI_Send(/* some message */);
unlock(mpi_lock);
/* eventually break out of loop */
}
}
void thread2_function(){
while(true){
/* things happen */
char *buffer = CREATE_BUFFER();
lock(mpi_lock);
MPI_Recv(buffer /* some message stored in buffer */);
unlock(mpi_lock);
/* eventually break out of loop */
}
}
int main(){
create_thread(thread1_function);
create_thread(thread2_function);
return 0;
}
这是我的问题:这是正确的方法和/或是否有必要?在我的情况下,我必须假设在thread2_function()中收到的消息之间可能存在很大的时间间隔。有没有办法阻止thread1_function()在能够执行发送之前必须等待thread2_function()完成接收?
我已经知道MPI_THREAD_MULTIPLE,但系统限制意味着我无法使用。
我愿意接受重构代码的建议,但我的目标是让一个“主”线程不断地工作,MPI_Send的结果不会中断,而另一个线程管理接收并附加到主线程的队列。
提前致谢。
答案 0 :(得分:2)
仅使用MPI_THREAD_SERIALIZED
时,此类外部锁定(或其他类似的同步方案)非常必要。解决问题的唯一方法是使用MPI_THREAD_MULTIPLE
,但这似乎对您无法解决。另外,在这种情况下,请不要尝试使用MPI_THREAD_SINGLE
或MPI_THREAD_FUNNELED
而不是SERIALIZED
,有些平台和实现会导致小块MPI被破坏。< / p>
如果您在进程内的线程之间发送/接收消息,则上面发布的代码可能会出现问题。如果thread2
已启动,则获取锁定并在MPI_Recv
能够获取锁定之前输入thread1
并通过thread2
将消息发布到MPI_Send
,然后因为thread1
永远无法获得锁定而陷入僵局。如果在干扰获取锁定的进程之间存在一个消息循环(当在进程/线程之间查看消息传输时),则在某些情况下仍会发生类似的死锁。
在此类情况下避免死锁的最佳选择是避免阻止阻止MPI调用,而是使用非阻塞调用,例如MPI_Irecv
和MPI_Test
。