【MPI】矩阵向量乘法

时间:2022-02-14 17:16:22

输入作乘法的次数K

然后输入矩阵和向量的维度n

然后输入一个n维向量

然后输入K个n阶方阵

程序会给出该向量连续与此K个方阵做乘法后的结果

主要用了MPI_Gather, MPI_Allgather, MPI_Bcast, MPI_Scatter 等

注意printf在终端中打印的时机会很玄学 往往会在程序完全执行完毕之后才会打印

注意 本程序将矩阵的所有行划分成一些段,分别分配给各个进程 仍然没有处理进程数无法整除维度n的情况

【MPI】矩阵向量乘法

typedef long long __int64;
#include "mpi.h"
#include <cstdio>
#include <cmath>
using namespace std;
int main(int argc, char* argv[]){
int my_rank=0, comm_sz=0, local_int=0, total_int=0;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
int n,zongci;
int* x;
if(my_rank==0){
scanf("%d%d",&zongci,&n);
}
MPI_Bcast(&zongci,1,MPI_INT,0,MPI_COMM_WORLD);
MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD);
x=new int[n];
if(my_rank==0){
for(int i=0;i<n;++i){
scanf("%d",&x[i]);
}
}
MPI_Bcast(x,n,MPI_INT,0,MPI_COMM_WORLD);
if(my_rank==0){
printf("第0次与%d*%d矩阵相乘后的x向量:\n",n,n);
for(int i=0;i<n;++i){
printf("%d\n",x[i]);
}
puts("");
}
for(int ci=1;ci<=zongci;++ci){
int* local_A=new int[n*n/comm_sz];
int* A=new int[n*n];
if(my_rank==0){
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
scanf("%d",&A[i*n+j]);
}
}
MPI_Scatter(A,n*n/comm_sz,MPI_INT,local_A,n*n/comm_sz,MPI_INT,0,MPI_COMM_WORLD);
delete[] A;
}
else{
MPI_Scatter(A,n*n/comm_sz,MPI_INT,local_A,n*n/comm_sz,MPI_INT,0,MPI_COMM_WORLD);
}
int* local_x=new int[n/comm_sz];
for(int i=0;i<n/comm_sz;++i){
local_x[i]=0;
for(int j=0;j<n;++j){
local_x[i]+=local_A[i*n+j]*x[j];
}
}
if(ci<zongci){
MPI_Allgather(local_x,n/comm_sz,MPI_INT,x,n/comm_sz,MPI_INT,MPI_COMM_WORLD);
}
else{
MPI_Gather(local_x,n/comm_sz,MPI_INT,x,n/comm_sz,MPI_INT,0,MPI_COMM_WORLD);
}
if(my_rank==0){
printf("第%d次与%d*%d矩阵相乘后的x向量:\n",ci,n,n);
for(int i=0;i<n;++i){
printf("%d\n",x[i]);
}
puts("");
}
delete[] local_x;
}
delete[] x;
MPI_Finalize();
return 0;
}