在 C 中使用 MPI 收集拆分二维数组
Gather a split 2D array with MPI in C
我需要将这部分很长的代码改编成c中的mpi。
for (i = 0; i < total; i++) {
sum = A[next][0][0]*B[i][0] + A[next][0][1]*B[i][1] + A[next][0][2]*B[i][2];
next++;
while (next < last) {
col = column[next];
sum += A[next][0][0]*B[col][0] + A[next][0][1]*B[col][1] + A[next][0][2]*B[col][2];
final[col][0] += A[next][0][0]*B[i][0] + A[next][1][0]*B[i][1] + A[next][2][0]*B[i][2];
next++;
}
final[i][0] += sum;}
我在想这样的代码:
for (i = 0; i < num_threads; i++) {
for (j = 0; j < total; j++) {
check_thread[i][j] = false;
}
}
part = total / num_threads;
for (i = thread_id * part; i < ((thread_id + 1) * part); i++) {
sum = A[next][0][0]*B[i][0] + A[next][0][1]*B[i][1] + A[next][0][2]*B[i][2];
next++;
while (next < last) {
col = column[next];
sum += A[next][0][0]*B[col][0] + A[next][0][1]*B[col][1] + A[next][0][2]*B[col][2];
if (!check_thread[thread_id][col]) {
check_thread[thread_id][col] = true;
temp[thread_id][col] = 0.0;
}
temp[thread_id][col] += A[next][0][0]*B[i][0] + A[next][1][0]*B[i][1] + A[next][2][0]*B[i][2];
next++;
}
if (!check_thread[thread_id][i]) {
check_thread[thread_id][i] = true;
temp[thread_id][i] = 0.0;
}
temp[thread_id][i] += sum;
}
*
for (i = 0; i < total; i++) {
for (j = 0; j < num_threads; j++) {
if (check_thread[j][i]) {
final[i][0] += temp[j][i];
}
}
}
然后我需要将所有临时部分集中在一起,我在想 MPI_Allgather
和类似这样的东西,就在最后两个 for (where *):
MPI_Allgather(temp, (part*sizeof(double)), MPI_DOUBLE, temp, sizeof(**temp), MPI_DOUBLE, MPI_COMM_WORLD);
但是我得到一个执行错误,是否可以在同一个变量中发送和接收?如果不能,在这种情况下其他解决方案是什么?
您正在使用错误的参数调用 MPI_Allgather:
MPI_Allgather(temp, (part*sizeof(double)), MPI_DOUBLE, temp, sizeof(**temp), MPI_DOUBLE, MPI_COMM_WORLD);
相反你应该有 (source) :
MPI_Allgather
Gathers data from all tasks and distribute the combined data to all
tasks
Input Parameters
sendbuf starting address of send buffer (choice)
sendcount number of elements in send buffer (integer)
sendtype data type of send buffer elements (handle)
recvcount number of elements received from any process (integer)
recvtype data type of receive buffer elements (handle)
comm communicator (handle)
你的 sendcount
和 recvcount
参数都是错误的,而不是 (part*sizeof(double)) 和 sizeof(**temp) 你应该传递矩阵 temp
将由所有相关进程收集。
如果该矩阵在内存中连续分配,则可以在一次调用中收集该矩阵,如果它是作为指针数组创建的,则必须为矩阵的每一行调用 MPI_Allgather
,或改用 MPI_Allgatherv。
Is it possible to send and receive in the same variable?
是的,通过使用 In-place Option
When the communicator is an intracommunicator, you can perform an
all-gather operation in-place (the output buffer is used as the input
buffer). Use the variable MPI_IN_PLACE as the value of sendbuf. In
this case, sendcount and sendtype are ignored. The input data of each
process is assumed to be in the area where that process would receive
its own contribution to the receive buffer. Specifically, the outcome
of a call to MPI_Allgather that used the in-place option is identical
to the case in which all processes executed n calls to
MPI_GATHER ( MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, recvbuf,
recvcount, recvtype, root, comm )
我需要将这部分很长的代码改编成c中的mpi。
for (i = 0; i < total; i++) {
sum = A[next][0][0]*B[i][0] + A[next][0][1]*B[i][1] + A[next][0][2]*B[i][2];
next++;
while (next < last) {
col = column[next];
sum += A[next][0][0]*B[col][0] + A[next][0][1]*B[col][1] + A[next][0][2]*B[col][2];
final[col][0] += A[next][0][0]*B[i][0] + A[next][1][0]*B[i][1] + A[next][2][0]*B[i][2];
next++;
}
final[i][0] += sum;}
我在想这样的代码:
for (i = 0; i < num_threads; i++) {
for (j = 0; j < total; j++) {
check_thread[i][j] = false;
}
}
part = total / num_threads;
for (i = thread_id * part; i < ((thread_id + 1) * part); i++) {
sum = A[next][0][0]*B[i][0] + A[next][0][1]*B[i][1] + A[next][0][2]*B[i][2];
next++;
while (next < last) {
col = column[next];
sum += A[next][0][0]*B[col][0] + A[next][0][1]*B[col][1] + A[next][0][2]*B[col][2];
if (!check_thread[thread_id][col]) {
check_thread[thread_id][col] = true;
temp[thread_id][col] = 0.0;
}
temp[thread_id][col] += A[next][0][0]*B[i][0] + A[next][1][0]*B[i][1] + A[next][2][0]*B[i][2];
next++;
}
if (!check_thread[thread_id][i]) {
check_thread[thread_id][i] = true;
temp[thread_id][i] = 0.0;
}
temp[thread_id][i] += sum;
}
*
for (i = 0; i < total; i++) {
for (j = 0; j < num_threads; j++) {
if (check_thread[j][i]) {
final[i][0] += temp[j][i];
}
}
}
然后我需要将所有临时部分集中在一起,我在想 MPI_Allgather
和类似这样的东西,就在最后两个 for (where *):
MPI_Allgather(temp, (part*sizeof(double)), MPI_DOUBLE, temp, sizeof(**temp), MPI_DOUBLE, MPI_COMM_WORLD);
但是我得到一个执行错误,是否可以在同一个变量中发送和接收?如果不能,在这种情况下其他解决方案是什么?
您正在使用错误的参数调用 MPI_Allgather:
MPI_Allgather(temp, (part*sizeof(double)), MPI_DOUBLE, temp, sizeof(**temp), MPI_DOUBLE, MPI_COMM_WORLD);
相反你应该有 (source) :
MPI_Allgather
Gathers data from all tasks and distribute the combined data to all tasks
Input Parameters
sendbuf starting address of send buffer (choice)
sendcount number of elements in send buffer (integer)
sendtype data type of send buffer elements (handle)
recvcount number of elements received from any process (integer)
recvtype data type of receive buffer elements (handle)
comm communicator (handle)
你的 sendcount
和 recvcount
参数都是错误的,而不是 (part*sizeof(double)) 和 sizeof(**temp) 你应该传递矩阵 temp
将由所有相关进程收集。
如果该矩阵在内存中连续分配,则可以在一次调用中收集该矩阵,如果它是作为指针数组创建的,则必须为矩阵的每一行调用 MPI_Allgather
,或改用 MPI_Allgatherv。
Is it possible to send and receive in the same variable?
是的,通过使用 In-place Option
When the communicator is an intracommunicator, you can perform an all-gather operation in-place (the output buffer is used as the input buffer). Use the variable MPI_IN_PLACE as the value of sendbuf. In this case, sendcount and sendtype are ignored. The input data of each process is assumed to be in the area where that process would receive its own contribution to the receive buffer. Specifically, the outcome of a call to MPI_Allgather that used the in-place option is identical to the case in which all processes executed n calls to
MPI_GATHER ( MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, recvbuf, recvcount, recvtype, root, comm )