2015-05-05 55 views
-1

我很新的MPI,所以我试图做Haversine distance在C中的计算方法,到目前为止它似乎工作,但我注意到结果是不正确的,也许错误,我用MPI方法,这里是我的代码:MPI Haversine在C中的距离计算

#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,这会导致计算错误。

如果您发现一些错误,请指出。 感谢提前:)

+3

如果你想找到一个bug的帮助,你需要真正描述问题,告诉我们输出是错误的,描述你期望的等等。你可以放心地假设世界其他地方不知道什么Haversine距离我们的头顶。 –

+1

但是,作为一个起点,您可以查看'MPI_Bcast'和'MPI_Gather'确实分发并检索您的工作人员的数据。 –

回答

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==4MPI_Send()第一个电话将发送destination[offset][0],destination[offset][1],destination[offset+1][0],destination[offset+1][1]因为这些元素对应于一维数组将被发送。第二个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()