2013-05-21 136 views
1

我想使用MPI和Pthreads实现以下功能,但面临一些错误:从多线程调用MPI功能

每个处理器都有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. 
+0

您可以更新您的问题,以包括一个最小的,可编译的代码示例,重现您的问题? –

+1

我已经在MPI [这里](http://stackoverflow.com/a/14837206/1374437)中写了关于线程支持的详细解释。 –

+0

@Hristo:你的解释写在这一点上。感谢这篇文章。 – user2403959

回答

1

(因为你没有提供一个例子,下面只是猜测。)而不是MPI_INIT

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

+1

如果不支持'MPI_THREAD_MULTIPLE','MPI_Init_thread()'不会失败,而是会以低线程支持级别进行初始化。实际的线程支持级别在'provided'输出参数中返回。 –

+0

@HristoIliev:确实;答案固定。 – janneb

1

它与MPICH2只有一行更改。

而不是使用MPI_INIT的,请使用以下行:

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

感谢大家的帮助,并及时答复!