*主任务首先初始化一个数组,然后将该数组的相等部分分配给其他任务。在其他任务接收到它们的数组部分之后,它们对每个数组元素执行加法运算。它们还为它们的数组部分保持一个总和。主任务同样使用其部分数组。作为每个非主人 任务完成后,他们将更新的数组部分发送给主服务器。 MPI集体通信呼叫用于收集每个任务维护的总和。最后,主任务显示最终数组的选定部分和所有数组元素的全局总和。 *
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#define ARRAYSIZE 16000000
#define MASTER
float data[ARRAYSIZE];
int main (int argc, char *argv[])
{
int numtasks, taskid, rc, dest, source, offset, i, j, tag1,
tag2, chunksize;
float mysum, sum;
float update(int myoffset, int chunk, int myid);
MPI_Status status;
/******Initializations******/
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
if (numtasks % 4 != 0) {
printf("Quitting. Number of MPI tasks must be divisible by 4. \n");
MPI_Abort(MPI_COMM_WORLD, rc);
exit(0);
}
MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
chunksize = ARRAYSIZE / numtasks;
tag2 = 1;
tag1 = 2;
/******Master task only ******/
if (taskid == MASTER){
/* Initialize the array */
sum = 0;
for (i = 0; i < ARRAYSIZE; i++){
data[i] = i * 1.0;
sum = sum + data[i];
}
printf("Initialized array sum = %e\n", sum);
/* Send each task its portion of the array - mater keeps 1st part */
offset = chunksize;
for (dest = 1; dest < numtasks; dest++){
MPI_Send(&offset, 1, MPI_INT, dest, tag1, MPI_COMM_WORLD);
MPI_Send(&data[offset], chunksize, MPI_FLOAT, dest, tag2, MPI_COMM_WRLD);
printf("Sent %d elements to task %d offset = %d\n, chunksize, dest, offset);
offset = offset + chunksize;
}
/* Master does its part of the work */
offset = 0;
mysum = update(offset, chunksize, taskid);
/* Get final sum */
MPI_Reduce(&mysum, &sum, 1, MPI_FLOAT, MPI_SUM, MASTER, MPI_COMM_WORLD);
printf("***Final sum = %e ***\n", sum);
} /* end of master section */
/******Non-master tasks only ******/
if (taskid > MASTER){
/* Receive my portion of array from the master task */
source = MASTER;
MPI_Recv(&offset, 1, MPI_INT, source, tag1, MPI_COMM_WORLD, &status);
MPI_Recv(&data[offset], chunksize, MPI_FLOAT, source, tag2, MPI_COMM_WORLD, &status);
mysum = update(offset, chunksize, taskid);
MPI_Reduce(&mysum, &sum, 1, MPI_FLOAT, MPI_SUM, MASTER, MPI_COMM_WORLD);
} /* end of non-master */
MPI_Finalize();
} /* end of main */
float update(int myoffset, int chunk, int myid){
int i;
float mysum;
/* Perform addition to each of my array elements and keep my sum */
mysum = 0;
for (i = myoffset; i < myoffset + chunk; i++){
mysum = mysum + data[i];
}
printf("Task %d mysum = %e\n", myid, mysum);
return mysum;
}
/******The result of this program is: ******/
MPI task 0 has started...
MPI task 1 has started...
MPI task 2 has started...
MPI task 3 has started...
Initialized array sum = 1.335708e+14
Sent 4000000 elements to task 1 offset= 4000000
Sent 4000000 elements to task 2 offset= 8000000
Task 1 mysum = 2.442024e+13
Sent 4000000 elements to task 3 offset= 12000000
Task 2 mysum = 3.991501e+13
Task 3 mysum = 5.809336e+13
Task 0 mysum = 7.994294e+12
Sample results:
0.000000e+00 1.000000e+00 2.000000e+00 3.000000e+00 4.000000e+00
4.000000e+06 4.000001e+06 4.000002e+06 4.000003e+06 4.000004e+06
8.000000e+06 8.000001e+06 8.000002e+06 8.000003e+06 8.000004e+06
1.200000e+07 1.200000e+07 1.200000e+07 1.200000e+07 1.200000e+07
*** Final sum= 1.304229e+14 ***
*所以我的问题是为什么这两个总和不能保持相同的值**
答案 0 :(得分:0)
您将结果存储在32位浮点数(即浮点数)中,该数字不足以维持您需要的所有精度。您所看到的是一个典型示例,说明舍入错误如何累积,具体取决于您将数字加在一起的顺序。
如果您只是用双打替换所有花车,则可以:
mpiexec -n 4 ./arraysum
Initialized array sum = 1.280000e+14
Sent 4000000 elements to task 1 offset = 4000000
Task 1 mysum = 2.400000e+13
Sent 4000000 elements to task 2 offset = 8000000
Task 2 mysum = 4.000000e+13
Sent 4000000 elements to task 3 offset = 12000000
Task 0 mysum = 7.999998e+12
Task 3 mysum = 5.600000e+13
***Final sum = 1.280000e+14 ***