【问题标题】:Calling MPI functions from multiple threads从多个线程调用 MPI 函数
【发布时间】:2013-05-15 17:47:17
【问题描述】:

我想使用 MPI 和 Pthreads 实现以下内容,但遇到了一些错误:

每个处理器将有 2 个线程。每个处理器的一个线程将向其他处理器发送数据,而另一个线程将从其他处理器接收数据。当我实现它时,它会给出分段错误错误,其中包含一些消息,例如“当前字节 -40,总字节 0,远程 id 5”。

仅出于测试目的,当我每个处理器仅使用一个线程并且发送或接收数据时,不会发生错误。

我找到了信息“一般来说,如果多个线程进行 MPI 调用,可能会出现问题。程序可能会失败或出现意外行为。如果 MPI 调用必须在线程内进行,则只能由一个线程进行。 "在以下链接中:https://computing.llnl.gov/tutorials/pthreads/

我想每个处理器使用两个线程,其中一个线程将使用 MPI_Send 函数发送一些数据,而另一个线程将接收 MPI_Recv 函数以接收数据,而不使用任何锁定机制。有谁知道如何在不使用互斥锁或锁定机制的情况下实现这一点或如何使用多个线程调用 MPI 函数?

代码如下:

int rank, size, msg_num;

// thread function for sending messages
void *Send_Func_For_Thread(void *arg)
{
    int send, procnum, x;
    send = rank;

    for(x=0; x < msg_num; x++)
    {
        procnum = rand()%size;
        if(procnum != rank)
            MPI_Send(&send, 1, MPI_INT, procnum, 0, MPI_COMM_WORLD);
    }

// sending special message to other processors with tag = 128 to signal the finishing of sending message

    for (x = 0; x < size; x++)
    {
        if(x != rank)
            MPI_Send(&send, 1, MPI_INT, x, 128, MPI_COMM_WORLD);    
    }

    pthread_exit((void *)NULL);
}


// thread function for receiving messages

void *Recv_Func_For_Thread(void *arg)
{
    MPI_Status status;
    int recv, counter = 0;

    while(counter != size - 1)
    {
        MPI_Recv(&recv, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
        if(status.MPI_TAG == 128)
            counter++;
    }

    pthread_exit((void *)NULL);
}


int main(int argc, char **argv)
{
    void *stat;
    pthread_attr_t attr;
    pthread_t thread[2];

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);   // rank -> rank of this processor
    MPI_Comm_size(MPI_COMM_WORLD, &size);   // size -> total number of processors

    srand((unsigned)time(NULL));

    msg_num = atoi(argv[1]);

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    // thread 0 will be sending   messages
    pthread_create(&thread[0], &attr, Send_Func_For_Thread, (void *)0);

    // thread 1 will be receiving messages
    pthread_create(&thread[1], &attr, Recv_Func_For_Thread, (void *)1);

    pthread_attr_destroy(&attr);

    pthread_join(thread[0], &stat);
    pthread_join(thread[1], &stat);

    cout << "Finished : Proc " << rank << "\n";

    MPI_Finalize();
    pthread_exit((void *)NULL);
    return 0;   
}

Compile:
========

module load mvapich2/gcc;        mpicxx -lpthread -o demo demo.cpp

Run:
====
mpiexec -comm mpich2-pmi demo 10000000

I ran this program with 3 processors and got segmentation fault.

【问题讨论】:

  • 能否更新您的问题以包含一个最小的、可编译的代码示例来重现您的问题?
  • 我已经在 MPI here 中写了一个关于线程支持的详尽解释。
  • @Hristo:你的解释写得很中肯。感谢您的帖子。

标签: pthreads mpi


【解决方案1】:

(由于您没有提供示例,以下只是推测。)

您必须使用 MPI_Init_thread() 而不是 MPI_Init() 来初始化 MPI。如果我正确理解了您的解释,则“必需”参数的值必须为 MPI_THREAD_MULTIPLE。如果 MPI_Init_thread() 然后在“提供”参数中返回较低级别的线程支持,这意味着您的 MPI 实现不支持 MPI_THREAD_MULTIPLE;在这种情况下,您必须做其他事情。见http://www.mpi-forum.org/docs/mpi-20-html/node165.htm

【讨论】:

  • 如果不支持MPI_THREAD_MULTIPLEMPI_Init_thread() 不会失败,而是会使用较低的线程支持级别进行初始化。实际的线程支持级别在provided 输出参数中返回。
  • @HristoIliev:确实;答案固定。
【解决方案2】:

使用 MPICH2 只需要换行即可。

不要使用 MPI_Init,而是使用以下行:

int provided;
MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);

感谢大家的帮助和及时回复!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多