带散射集合的MPI矩阵乘法

我正在尝试使用C中的MPI进行矩阵乘法,我们必须做一个顺序和一个并行版本的版本。 我的并行版本没有给出正确的答案,我不知道为什么。 我想我没有向流程发送正确的通信,但我不能确定。 教授刚刚查看了不同的发送/接收/收集等消息,但没有真正详细介绍……我已经看到很多不同的例子,但没有完成,没有使用分散/聚集。 如果有人可以看看我的代码,并告诉我,如果有任何东西突然出现,我会很感激。 我很确定我的问题在于分散/收集消息或c矩阵的实际计算。

#define N 512 #include  #include  #include  #include  #include  #include "mpi.h" print_results(char *prompt, float a[N][N]); int main(int argc, char *argv[]) { int i, j, k, rank, size, tag = 99, blksz, sum = 0; float a[N][N], b[N][N], c[N][N]; char *usage = "Usage: %s file\n"; FILE *fd; double elapsed_time, start_time, end_time; struct timeval tv1, tv2; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (argc < 2) { fprintf (stderr, usage, argv[0]); return -1; } if ((fd = fopen (argv[1], "r")) == NULL) { fprintf (stderr, "%s: Cannot open file %s for reading.\n", argv[0], argv[1]); fprintf (stderr, usage, argv[0]); return -1; } for (i = 0; i < N; i++) for (j = 0; j < N; j++) fscanf (fd, "%f", &a[i][j]); for (i = 0; i < N; i++) for (j = 0; j < N; j++) fscanf (fd, "%f", &b[i][j]); MPI_Barrier(MPI_COMM_WORLD); gettimeofday(&tv1, NULL); MPI_Scatter(a, N*N/size, MPI_INT, a, N*N/size, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(b, N*N, MPI_INT, 0, MPI_COMM_WORLD); if (rank != 0) { for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { for (k = 0; k < N; k++) { sum = sum + a[i][k] * b[k][j]; } c[i][j] = sum; sum = 0; } } } MPI_Gather(c, N*N/size, MPI_INT, c, N*N/size, MPI_INT, 0, MPI_COMM_WORLD); MPI_Finalize(); gettimeofday(&tv2, NULL); elapsed_time = (tv2.tv_sec - tv1.tv_sec) + ((tv2.tv_usec - tv1.tv_usec)/1000000.0); printf ("elapsed_time=\t%lf (seconds)\n", elapsed_time); print_results("C = ", c); } print_results(char *prompt, float a[N][N]) { int i, j; printf ("\n\n%s\n", prompt); for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { printf(" %.2f", a[i][j]); } printf ("\n"); } printf ("\n\n"); } 

更新的部分代码:

 for (i=0;i<size; i++) { if (rank == i) { for (i = rank*(N/size); i < (rank*(N/size)+(N/size)); i++) { for (j = rank*(N/size); j < (rank*(N/size)+(N/size)); j++) { for (k = rank*N; k < rank*N+N; k++) { sum = sum + a[i][k] * b[k][j]; } c[i][j] = sum; sum = 0; } } } } 

代码中的第一个问题是size可能不会划分N 这意味着长度为N*N/size散射size包不一定发送整个矩阵。 这可能是最难对付的一点。

正如Greg Inozemtsev指出的那样,第二个问题是你将进程0从计算中排除,尽管它负责矩阵的一部分。

另一个问题是所有I / O操作(在开头读取系数并在结束时输出结果)应仅由进程0完成。

另请注意,您应该在前向声明和定义中指定print_result函数的返回类型(在本例中为void )。