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

Posted

技术标签:

【中文标题】MPI_Recv() 冻结程序,未从 C 中的 MPI_Send() 接收值【英文标题】:MPI_Recv() freezing program, not receiving value from MPI_Send() in C 【发布时间】:2019-04-29 17:30:38 【问题描述】:

我正在尝试在 MPI 中编写超快速排序的实现,但我遇到了一个问题,即进程卡在 MPI_Recv()

在使用 2 个进程进行测试时,似乎在 if (rank % comm_sz == 0)else 内部,进程 1 从未接收到来自进程 0 的数据透视表。进程 0 成功发送了它的数据透视表并正确地递归了该方法。如果放入一些打印调试语句并收到输出:

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

之后,来自 1 级的 post-recv 消息将不再打印。 Rank 0 打印其发送后消息并继续通过其数组部分。我对MPI_Send()MPI_Recv() 的实现是否有问题可能导致这种情况?

这是我的快速排序代码:

(作为参考,方法参数中的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);
            
    

【问题讨论】:

【参考方案1】:
Rank 0 sending pivot 7 to 1
MPI_Send(&pivot, 1, MPI_INT, partner, rank, MPI_COMM_WORLD);
                                      ^^^^

所以发件人标签为零。

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

接收者标签为一。

如果接收者只请求带有特定标签的消息,它将不会收到带有不同标签的消息。

有时在某些情况下,A 可能必须向 B 发送许多不同类型的消息。 MPI 允许发送者和接收者也可以在消息中指定消息 ID,而不是 B 必须通过额外的措施来区分所有这些消息(称为标签)。当进程 B 只请求具有某个标签号的消息时,具有不同标签的消息将被网络缓存,直到 B 准备好接收它们。 [MPI Tutorial -- Send and Receive]

【讨论】:

Doi,我不敢相信我一直在看这两行代码,却没有注意到我制作的标签不同。非常感谢您的帮助!

以上是关于MPI_Recv() 冻结程序,未从 C 中的 MPI_Send() 接收值的主要内容,如果未能解决你的问题,请参考以下文章

MPI_Recv 覆盖它不应访问的部分内存

为啥当我单击目标 c 中的按钮时未从 tableViewCell 获取文本字段数据?

c#多线程应用程序中的界面冻结

未从所选目录运行的文件

某些设备中的应用程序未从 iTunes Store 更新

bcp 未从任务调度程序运行