C 如何使用并行计算机(MPI)乘法矩阵
我正在努力让我的代码使用MPI运行。我正在尝试实现矩阵乘法 我的代码是这样的C 如何使用并行计算机(MPI)乘法矩阵,c,parallel-processing,mpi,C,Parallel Processing,Mpi,我正在努力让我的代码使用MPI运行。我正在尝试实现矩阵乘法 我的代码是这样的 有两个矩阵A和B 把一行一行地分散开来 广播矩阵B 计算 聚集 我已经写了代码…但是代码运行不正常。。。我犯了一个错误 我不知道为什么会发生这种情况…我尝试了很多次调整代码…但似乎总是有什么地方出错 有人能检查一下这个代码并告诉我为什么代码不起作用吗 我补充说: “散射矩阵” “收集答案”等等……所以,即使你能浏览一下这个节目的分散部分,告诉我为什么不对,我也会心存感激 #define N 512 #include &
#define N 512
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include "mpi.h"
void print_results(char *prompt, float result[N][N]);
int main(int argc, char *argv[])
{
int i, j, k;
MPI_Status status;
int process_rank;//rank of a process
int no_of_processes;//no. of processes
int Master_To_Slave = 0;
int Slave_To_Master = 5;
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;
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;
}
// Read input from file for matrices a and b.
// The I/O is not timed because this I/O needs
// to be done regardless of whether this program
// is run sequentially on one processor or in
// parallel on many processors. Therefore, it is
// irrelevant when considering speedup.
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]);
int num_of_rows_A = N;
int num_of_cols_A = N;
int num_of_rows_B = N;
int num_of_cols_B = N;
int lower_index_of_A;
int upper_index_of_A;
//TODO: Add a barrier prior to the time stamp.
MPI_Init(&argc, &argv); //initialize MPI operations
MPI_Barrier(MPI_COMM_WORLD); //Added Barrier
// Take a time stamp
gettimeofday(&tv1, NULL);
//TODO: Scatter the input matrices a and b.
MPI_Comm_rank(MPI_COMM_WORLD, &process_rank); //get the rank
MPI_Comm_size(MPI_COMM_WORLD, &no_of_processes); //get number of processes
if(process_rank==0){
fprintf (stderr, "Main process started");
fprintf (stderr, "No. of process %d",no_of_processes);
fprintf (stderr, "\n\n");
fprintf (stderr, "\n\n");
for( i=1; i<no_of_processes;i++)
{
int rows_per_process = num_of_rows_A/(no_of_processes-1);
lower_index_of_A = (i-1)*rows_per_process;
// fprintf (stderr, "Current lower Index of A %s",lower_index_of_A);
if(i+1==no_of_processes &&((num_of_rows_A%(no_of_processes-1))!=0))
{
upper_index_of_A=num_of_rows_A;
// fprintf (stderr, "Current upper Index of A %s",upper_index_of_A);
}
else
{
upper_index_of_A=lower_index_of_A+rows_per_process;
// fprintf (stderr, "Current upper Index of A %s",upper_index_of_A);
}
fprintf (stderr, "Lower index of A %d", lower_index_of_A);
fprintf (stderr, "Upper index of A %d", upper_index_of_A);
fprintf (stderr, "\n\n");
MPI_Send(&lower_index_of_A,1,MPI_INT,i,Master_To_Slave,MPI_COMM_WORLD); //send lower index
MPI_Send(&upper_index_of_A,1,MPI_INT,i,Master_To_Slave+1,MPI_COMM_WORLD);//send upper index
MPI_Send(&a[lower_index_of_A][0],(upper_index_of_A-lower_index_of_A)*num_of_cols_A,MPI_DOUBLE,i,Master_To_Slave+2,MPI_COMM_WORLD);//send rows of A
fprintf (stderr, "Scatter done");
}
MPI_Bcast(&b, num_of_rows_A*num_of_cols_B, MPI_DOUBLE, 0, MPI_COMM_WORLD);
fprintf (stderr, "Broadcast done");
}
else
{
MPI_Recv(&lower_index_of_A, 1, MPI_INT, 0, Master_To_Slave,MPI_COMM_WORLD, &status);
MPI_Recv(&upper_index_of_A, 1, MPI_INT, 0, Master_To_Slave+1,MPI_COMM_WORLD,&status);
MPI_Recv(&a[lower_index_of_A], (upper_index_of_A-lower_index_of_A)*num_of_cols_A, MPI_DOUBLE,0, Master_To_Slave+2,MPI_COMM_WORLD, &status);
//TODO: Add code to implement matrix multiplication (C=AxB) in parallel.
for( i=lower_index_of_A;i<upper_index_of_A;i++)
{
for( j=0;j<num_of_cols_B;j++)
{
for( k=0;k<num_of_rows_B;k++)
{
c[i][j]+=(a[i][k]*b[k][j]);
}
}
}
MPI_Send(&lower_index_of_A, 1, MPI_INT, 0, Slave_To_Master,MPI_COMM_WORLD);
MPI_Send(&upper_index_of_A, 1, MPI_INT, 0, Slave_To_Master+1,MPI_COMM_WORLD);
MPI_Send(&c[lower_index_of_A], (upper_index_of_A-lower_index_of_A)*num_of_cols_B, MPI_DOUBLE,0, Slave_To_Master+2,MPI_COMM_WORLD);
}
//TODO: Gather partial result back to the master process.
if(process_rank==0)
{
for(i=1;i<no_of_processes;i++)
{
MPI_Recv(&lower_index_of_A, 1, MPI_INT, i, Slave_To_Master, MPI_COMM_WORLD, &status);
//receive upper bound from a slave
MPI_Recv(&upper_index_of_A, 1, MPI_INT, i, Slave_To_Master + 1, MPI_COMM_WORLD, &status);
//receive processed data from a slave
MPI_Recv(&c[lower_index_of_A][0], (upper_index_of_A - lower_index_of_A) * num_of_cols_B, MPI_DOUBLE, i, Slave_To_Master + 2, MPI_COMM_WORLD, &status);
}
}
// Take a time stamp. This won't happen until after the master
// process has gathered all the input from the other processes.
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
print_results("C = ", c);
}
void print_results(char *prompt, float result[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", result[i][j]);
}
printf ("\n");
}
printf ("\n\n");
}
#定义N 512
#包括
#包括
#包括
#包括“mpi.h”
作废打印结果(字符*提示,浮点结果[N][N]);
int main(int argc,char*argv[])
{
int i,j,k;
MPI_状态;
int进程\u秩;//进程的秩
int no_of_进程;//进程数
int Master_到_Slave=0;
int-Slave-To-Master=5;
浮动a[N][N]、b[N][N]、c[N][N];
char*usage=“用法:%s文件\n”;
文件*fd;
双倍运行时间、开始时间、结束时间;
结构时间值tv1,tv2;
如果(argc<2){
fprintf(标准,用法,argv[0]);
返回-1;
}
如果((fd=fopen(argv[1],“r”)==NULL){
fprintf(stderr,“%s:无法打开文件%s进行读取。\n”,
argv[0],argv[1]);
fprintf(标准,用法,argv[0]);
返回-1;
}
//从文件中读取矩阵a和b的输入。
//I/O未计时,因为此I/O需要
//无论此程序是否
//在一个处理器上或在中顺序运行
//在许多处理器上并行。因此
//考虑加速时不相关。
对于(i=0;i 对于(i=1;i每当发生这种情况时,我都会启动一个调试器
我总是推荐并行调试器,但我有偏见,因为我是开发它的团队之一,但它有助于发现此类错误。您也可以尝试GDB,但这将需要更多的手动干预来处理多个进程
在您的例子中,您发布的代码在my MPI(Open MPI)中没有分段错误,它实际上挂起在进程0中的MPI_Bcast,其余挂起在其循环分支中的MPI_发送。这是因为排名1和更高级别的代码没有调用MPI_Bcast:它们需要匹配发送方,排名0,然后接收数据
为什么不下载一个调试器,自己看看呢?一旦你修复了这个广播不匹配问题,调试器会在你找到正在查找的分段错误后立即停止你的程序,并告诉你错误所在。每当发生这种情况时,我就会启动一个调试器
我总是推荐并行调试器,但我有偏见,因为我是开发它的团队之一,但它有助于发现此类错误。您也可以尝试GDB,但这将需要更多的手动干预来处理多个进程
在您的例子中,您发布的代码在my MPI(Open MPI)中没有分段错误,它实际上挂起在进程0中的MPI_Bcast,其余挂起在其循环分支中的MPI_发送。这是因为排名1和更高级别的代码没有调用MPI_Bcast:它们需要匹配发送方,排名0,然后接收数据
为什么不下载一个调试器并亲自查看-一旦您修复了此广播不匹配,调试器将在您找到正在查找的分段错误后立即停止您的程序,并显示错误所在。使用MPI函数MPI\u Scatter
和MPI\u Gather
,您可能会更成功这个问题正在成为一个常见问题,下面是另一个相关的问答——您可能会更成功地使用MPI函数MPI_Scatter
和MPI_Gather
。这个问题正在成为一个常见问题,所以,这里是另一个相关的问答--