我想在C中使用MPI進行矩陣乘法,我們必須做一個順序版本和一個並行版本。我的平行版本沒有給出正確的答案,我不知道爲什麼。我想我沒有給流程發送正確的溝通信息,但我無法確定。教授剛剛瀏覽了不同的發送/接收/收集等信息,但沒有詳細說明......我見過很多不同的例子,但沒有完成,也沒有使用分散/收集。如果任何人都可以看看我的代碼,並告訴我是否有任何東西出現在他們身上,我會很感激。我很確定我的問題出現在分散/收集消息或c矩陣的實際計算中。帶分散聚集的MPI矩陣乘法
#define N 512
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stddef.h>
#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;
}
}
}
}
有一件事跳出來:根應該在分散和收集中爲'recvbuf'提供神奇值'MPI_IN_PLACE'。只是爲'sendbuf'和'recvbuf'提供相同的指針在技術上違反了規範。另外,'MPI_Finalize'可能需要很長時間。你應該不會計時。 –
對不起,'MPI_IN_PLACE'應該在'MPI_Gather'中爲'sendbuf'提供。此外,根參與分散和收集,但是然後您將其排除在計算之外。它應該像其他行列一樣參與進來。 –
除了Greg Inozemtsev和Francesco已經發現的內容之外,您的計算內核在整個矩陣「a」中循環,而不僅僅是駐留在當前級別內存中的部分。 「i」循環的範圍應該相應地加以限制。 MPI還提供'MPI_Wtime()'定時器函數,它具有與'gettimeofday'相同的精度,因爲MPI標準建議實現者使用最高分辨率的定時器。 –