简体   繁体   English

MPI_Recv()冻结程序,未从C中的MPI_Send()接收值

[英]MPI_Recv() freezing program, not receiving value from MPI_Send() in C

I'm trying to write an implementation of a hyper quicksort in MPI, but I'm having an issue where a process gets stuck on MPI_Recv() . 我正在尝试在MPI中编写超快速排序的实现,但遇到一个问题,即进程卡在MPI_Recv()

While testing with 2 processes, it seems that inside the else of the if (rank % comm_sz == 0) , process 1 is never receiving the pivot from process 0. Process 0 successfully sends its pivot and recurses through the method correctly. 在使用2个进程进行测试时,似乎在if (rank % comm_sz == 0)else中,进程1从未收到进程0的数据。 If put in some print debug statements and received the output: 如果放入一些打印调试语句并收到输出:

(arr, 0, 2, 0, 9)
Rank 0 sending pivot 7 to 1
(arr, 1, 2, 0, 9)
Rank 1 pre-recv from 0

After which, the post-recv message from rank 1 never prints. 此后,永远不会打印排名1的post-recv消息。 Rank 0 prints its post-send message and continues through its section of the array. 等级0打印其发送后消息,并继续通过数组的该部分。 Is there something wrong with my implementation of MPI_Send() or MPI_Recv() that may be causing this? 我的MPI_Send()MPI_Recv()实现是否存在问题,可能会导致这种情况?

Here is my code for the quicksort: 这是我的快速排序代码:

(For reference, comm_sz in the parameters for the method refers to the number of processes looking at that section of the array.) (作为参考,该方法的参数中的comm_sz指的是查看数组该部分的进程数。)

void hyper_quick(int *array, int rank, int comm_sz, int s, int e) {
    printf("(arr, %d, %d, %d, %d)\n", rank, comm_sz, s, e);
    // Keeps recursing until there is only one element
    if (s < e) {
            int pivot;
            if (comm_sz > 1) {
                    // One process gets a random pivot within its range and sends that to every process looking at that range
                    if (rank % comm_sz == 0) {
                            pivot = rand() % (e - s) + s;
                            for (int i = rank + 1; i < comm_sz; i++) {
                                    int partner = rank + i;
                                    printf("Rank %d sending pivot %d to %d\n", rank, pivot, partner);
                                    MPI_Send(&pivot, 1, MPI_INT, partner, rank, MPI_COMM_WORLD);
                                    printf("Rank %d successfully sent %d to %d\n", rank, pivot, partner);
                            }
                    }
                    else {
                            int partner = rank - (rank % comm_sz);
                            printf("Rank %d pre-recv from %d\n", rank, partner);
                            MPI_Recv(&pivot, 1, MPI_INT, partner, rank, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
                            printf("Rank %d received pivot %d from %d\n", rank, pivot, partner);
                    }
            }
            else {
                    pivot = rand() % (e - s) + s;
            }
            int tmp = array[pivot];
            array[pivot] = array[e];
            array[e] = tmp;
            // Here is where the actual quick sort happens
            int i = s;
            int j = e - 1;
            while (i < j) {
                    while (array[e] >= array[i] && i < j) {
                            i++;
                    }
                    while (array[e] < array[j] && i < j) {
                            j--;
                    }
                    if (i < j) {
                            tmp = array[i];
                            array[i] = array[j];
                            array[j] = tmp;
                    }
            }
            if (array[e] < array[i]) {
                    tmp = array[i];
                    array[i] = array[e];
                    array[e] = tmp;
                    pivot = i;
            }
            else {
                    pivot = e;
            }
            // Split remaining elements between remaining processes
            if (comm_sz > 1) {
                    // Elements greater than pivot
                    if (rank % comm_sz >= comm_sz/2) {
                            hyper_quick(array, rank, comm_sz/2, pivot + 1, e);
                    }
                    // Elements lesser than pivot
                    else {
                            hyper_quick(array, rank, comm_sz/2, s, pivot - 1);
                    }
            }
            // Recurse remaining elements in current process
            else {
                    hyper_quick(array, rank, 1, s, pivot - 1);
                    hyper_quick(array, rank, 1, pivot + 1, e);
            }
    }
Rank 0 sending pivot 7 to 1
MPI_Send(&pivot, 1, MPI_INT, partner, rank, MPI_COMM_WORLD);
                                      ^^^^

So the sender tag is zero. 因此,发件人标签为零。

Rank 1 pre-recv from 0
MPI_Recv(&pivot, 1, MPI_INT, partner, rank, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
                                      ^^^^

And the receiver tag is one. 接收器标签是一个。

If the receiver asks for only messages with a specific tag, it will not receive a message with a different tag. 如果接收方仅要求带有特定标签的消息,则它将不会收到具有其他标签的消息。

Sometimes there are cases when A might have to send many different types of messages to B. Instead of B having to go through extra measures to differentiate all these messages, MPI allows senders and receivers to also specify message IDs with the message (known as tags). 有时,在某些情况下,A可能必须向B发送许多不同类型的消息。MPI无需发送者采取额外的措施来区分所有这些消息,而是使发送者和接收者还可以通过消息指定消息ID(称为标记) )。 When process B only requests a message with a certain tag number, messages with different tags will be buffered by the network until B is ready for them. 当进程B仅请求具有特定标签号的消息时,具有不同标签的消息将被网络缓冲,直到B为它们准备好为止。 [ MPI Tutorial -- Send and Receive ] [ MPI教程-发送和接收 ]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM