我对MPI很新,所以我尝试在C中做Haversine distance计算方法,到目前为止似乎工作但是我注意到结果不正确,也许我使用的MPI方法有问题,这是我的代码:
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define ROW 10 /* number of rows in matrix */
#define COLUMN 2 /* number of columns in matrix */
#define R 6371 /* averange radius of Earth */
#define MASTER 0 /* taskid of first task */
#define FROM_MASTER 1 /* setting a message type */
#define FROM_WORKER 2 /* setting a message type */
int main(int argc, char *argv[])
{
int numtasks, /* number of tasks in partition */
taskid, /* a task identifier */
numworkers, /* number of worker tasks */
source, /* task id of message source */
dest, /* task id of message destination */
mtype, /* message type */
rows, /* rows of matrix A sent to each worker */
averow, extra, offset, /* used to determine rows sent to each worker */
i, j, rc; /* misc */
double target[1][COLUMN], /* longitude and latitude of target */
dlat, dlon, /* longitude and latitude of destination */
a, c, d, /* variable for calculation */
destination[ROW][COLUMN], /* matrix dest for listed destination */
result[ROW]; /* result in matrix */
const char *name[ROW]; /* name of destination */
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
if (numtasks < 2) {
printf("Memerlukan minimal dua MPI tasks. Membatalkan...\n");
MPI_Abort(MPI_COMM_WORLD, rc);
exit(1);
}
numworkers = numtasks - 1;
/**************************** master task ************************************/
if (taskid == MASTER)
{
printf("MPI dengan %d tasks.\n", numtasks);
printf("Memulai...\n");
target[0][0] = -6.9167;
target[0][1] = 107.6000;
destination[0][0] = -6.1745;
destination[0][1] = 106.8227;
name[0] = "Jakarta";
destination[1][0] = -6.9167;
destination[1][1] = 107.6000;
name[1] = "Bandung";
destination[2][0] = -7.8014;
destination[2][1] = 110.3644;
name[2] = "Jogja";
destination[3][0] = -7.2653;
destination[3][1] = 112.7425;
name[3] = "Surabaya";
destination[4][0] = -5.5500;
destination[4][1] = 95.3167;
name[4] = "Aceh";
destination[5][0] = 3.5833;
destination[5][1] = 98.6667;
name[5] = "Medan";
destination[6][0] = -5.1333;
destination[6][1] = 119.4167;
name[6] = "Makassar";
destination[7][0] = -0.9500;
destination[7][1] = 100.3531;
name[7] = "Padang";
destination[8][0] = -8.6500;
destination[8][1] = 115.2167;
name[8] = "Denpasar";
destination[9][0] = -0.8667;
destination[9][1] = 134.0833;
name[9] = "Irian Jaya";
/* Send matrix data to the worker tasks */
averow = ROW / numworkers;
extra = ROW%numworkers;
offset = 0;
mtype = FROM_MASTER;
for (dest = 1; dest <= numworkers; dest++)
{
rows = (dest <= extra) ? averow + 1 : averow;
MPI_Send(&offset, 1, MPI_INT, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&rows, 1, MPI_INT, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&target[0][0], 1, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&target[0][1], 1, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&destination[offset][0], rows, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&destination[offset][1], rows, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
offset = offset + rows;
}
/* Receive results from worker tasks */
mtype = FROM_WORKER;
for (i = 1; i <= numworkers; i++)
{
source = i;
MPI_Recv(&offset, 1, MPI_INT, source, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&rows, 1, MPI_INT, source, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&result[offset], rows, MPI_DOUBLE, source, mtype, MPI_COMM_WORLD, &status);
}
/* Print results */
printf("******************************************************\n");
printf("Hasil:\n");
for (i = 0; i<ROW; i++)
{
printf("Jarak ke %s: ", name[i]);
printf("%f", result[i]);
printf(" km\n");
}
printf("\n******************************************************\n");
printf("Selesai.\n");
}
/**************************** worker task ************************************/
if (taskid > MASTER)
{
mtype = FROM_MASTER;
MPI_Recv(&offset, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&rows, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&target[0][0], 1, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&target[0][1], 1, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&destination[offset][0], rows, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status);
MPI_Recv(&destination[offset][1], rows, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status);
for (j = offset; j<offset + rows; j++)
{
dlon = destination[j][1] - target[0][1];
/* printf("dlon ke %i : %f \n", j, dlon); */
dlat = destination[j][0] - target[0][0];
/* printf("dlat ke %i : %f \n", j, dlat); */
a = pow((sin(dlat / 2)), 2) + (cos(target[0][0]) * cos(destination[j][0]) * pow((sin(dlon / 2)), 2));
/* printf("a ke %i : %f \n", j, a); */
c = 2 * atan2(sqrt(a), sqrt(1 - a));
/* printf("c ke %i : %f \n", j, c); */
d = R * c;
/* printf("d ke %i : %f \n", j, d); */
result[j] = d;
}
mtype = FROM_WORKER;
MPI_Send(&offset, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD);
MPI_Send(&rows, 1, MPI_INT, MASTER, mtype, MPI_COMM_WORLD);
MPI_Send(&result[offset], rows, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD);
}
MPI_Finalize();
}
此代码应显示距离每个地方的距离,因为它是MPI,它应该具有完全相同的结果,但结果实际上会发生变化。 此外,发送给worker的一些数据等于0,这导致计算错误。
如果您发现有些错误,请指出。 在此先感谢:)
答案 0 :(得分:0)
问题来自:
MPI_Send(&destination[offset][0], rows, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
MPI_Send(&destination[offset][1], rows, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
如果rows==4
MPI_Send()
的第一次调用将发送destination[offset][0],destination[offset][1],destination[offset+1][0],destination[offset+1][1]
,因为这些元素对应于将要发送的1D数组。第二个MPI_Send
来电发送destination[offset][1],destination[offset+1][0],destination[offset+1][1],destination[offset+2][0]
。这意味着永远不会发送destination[offset+3][1]
!
您似乎想要执行:
MPI_Send(&destination[offset][0], 2*rows, MPI_DOUBLE, dest, mtype, MPI_COMM_WORLD);
此操作将同时执行两行:第二个操作将被注释。 接收操作也应该改变:
MPI_Recv(&destination[offset][0],2*rows, MPI_DOUBLE, MASTER, mtype, MPI_COMM_WORLD, &status);
看看MPI_Scatterv()
功能:它完全符合您的要求。查看MPI_Bcast()
和MPI_Gatherv()