使用pthreads正确使用MPI_THREAD_SERIALIZED

时间:2011-04-27 22:30:49

标签: pthreads mutex mpi

在阅读了一些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的结果不会中断,而另一个线程管理接收并附加到主线程的队列。

提前致谢。

1 个答案:

答案 0 :(得分:2)

仅使用MPI_THREAD_SERIALIZED时,此类外部锁定(或其他类似的同步方案)非常必要。解决问题的唯一方法是使用MPI_THREAD_MULTIPLE,但这似乎对您无法解决。另外,在这种情况下,请不要尝试使用MPI_THREAD_SINGLEMPI_THREAD_FUNNELED而不是SERIALIZED,有些平台和实现会导致小块MPI被破坏。< / p>

如果您在进程内的线程之间发送/接收消息,则上面发布的代码可能会出现问题。如果thread2已启动,则获取锁定并在MPI_Recv能够获取锁定之前输入thread1并通过thread2将消息发布到MPI_Send,然后因为thread1永远无法获得锁定而陷入僵局。如果在干扰获取锁定的进程之间存在一个消息循环(当在进程/线程之间查看消息传输时),则在某些情况下仍会发生类似的死锁。

在此类情况下避免死锁的最佳选择是避免阻止阻止MPI调用,而是使用非阻塞调用,例如MPI_IrecvMPI_Test