c - 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()
.
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. 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. Rank 0 prints its post-send message and continues through its section of the array. Is there something wrong with my implementation of MPI_Send()
or MPI_Recv()
that may be causing this?
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.)
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);
^^^^
所以发件人标签为零。
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 教程——发送和接收]
推荐阅读
- android - Android webview 中的语音合成
- r - 4d 曲面图逻辑回归(x、y、z、颜色)
- c# - 在协程中实例化 GameObject 时出现无限问题
- docker-compose - 一个 docker-compose 文件中的两个网络
- javascript - 这。引用 Object 而不是 Window-Object
- java - 如何将两种不同的列表类型序列化/反序列化为单个顺序文件
- python - 即使在使用显式版本的 Pipfile 和 Pipfile.lock 之后用户之间的差异
- arrays - 计数不同子数组的数量
- python - 如何将numpy对象数组转换为包含每个对象元素的数组?
- javascript - 当光标在重叠的多段线上时,如何处理所有多段线上的点击事件?