mpi求矩阵转置:
第一个:
//棋盘
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<mpi.h>
#include<math.h>
using namespace std;
int **matrix;
int n;
MPI_Status status;
void init_matrix()
{
matrix = new int *[n];
for(int i=0; i<n; i++)
{
matrix[i] = new int[n];
}
int num = 1;
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
matrix[i][j] = num;
num++;
}
}
}
void show_matrix(int** mat)
{
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
cout<<mat[i][j]<<' ';
}
cout<<endl;
}
}
int main(int argc, char *argv[]){
n = atoi(argv[1]);
int myrank,size;
int sqrt_size,u,v,length;//进程数开根号即每行或每列的子块数,列号,行号,每个块的维数
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
sqrt_size = sqrt(size);//大矩阵一行有几个小矩阵
u = myrank%sqrt_size;//列
v = myrank/sqrt_size;//行
length = n/sqrt_size;//小矩阵边长
int *tmp = new int[length*length];//存储交换元素
//0号进程
if(myrank == 0)
{
double t1, t2;
init_matrix();
t1 = MPI_Wtime();
//寻找对应编号的子块
for(int i=0;i<sqrt_size;i++)
{
for(int j=0;j<sqrt_size;j++)
{
//0号进程转置
if(i==0 && j==0)
{
int q;
for(int ii=0;ii<length;ii++)
{
for(int jj=ii+1;jj<length;jj++)
{
q = matrix[ii][jj];
matrix[ii][jj] = matrix[jj][ii];
matrix[jj][ii] = q;
}
}
}
//向其他进程通信,分配任务
else
{
int cnt = 0;
for(int ii=length*i;ii<length*(i+1);ii++)
{
for(int jj=length*j;jj<length*(j+1);jj++)
{
tmp[cnt] = matrix[ii][jj];
cnt++;
}
}
MPI_Send(tmp,length*length,MPI_INT,i*sqrt_size+j,i*sqrt_size+j,MPI_COMM_WORLD);
}
}
}
//向其他进程通信,接收结果
for(int i=0;i<sqrt_size;i++){
for(int j=0;j<sqrt_size;j++){
if(i!=0 || j!=0){
MPI_Recv(tmp,length*length,MPI_INT,i*sqrt_size+j,i*sqrt_size+j,MPI_COMM_WORLD,&status);
//矩阵块沿非主对角线平移,ij块--ji块,
for(int ii=0;ii<length;ii++)
{
for(int jj=0;jj<length;jj++)
matrix[j*length+ii][i*length+jj] = tmp[ii*length+jj];
}
}
}
}
t2 = MPI_Wtime();
printf("time:%lf\n",t2-t1);
show_matrix(matrix);
}
// 其他进程转置自己的部分
else{
MPI_Recv(tmp,length*length,MPI_INT,0,myrank,MPI_COMM_WORLD,&status);
int t;
for(int i=0;i<length;i++){
for(int j=i+1;j<length;j++){
t = tmp[i*length+j];
tmp[i*length+j] = tmp[j*length+i];
tmp[j*length+i] = t;
}
}
MPI_Send(tmp,length*length,MPI_INT,0,myrank,MPI_COMM_WORLD);
}
delete matrix;
delete tmp;
MPI_Finalize();
return 0;
}
第二个:
//直角
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<mpi.h>
#include<math.h>
using namespace std;
int **matrix;
int n;
MPI_Status status;
void init_matrix()
{
matrix = new int *[n];
for(int i=0; i<n; i++)
{
matrix[i] = new int[n];
}
int num = 0;
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
matrix[i][j] = num;
num++;
}
}
}
void show_matrix(int** mat)
{
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
cout<<mat[i][j]<<' ';
}
cout<<endl;
}
}
int main(int argc, char *argv[]){
n = 10;//atoi(argv[1]);
int myrank,size;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
int *tmp = new int[n*n];//存储交换元素
int piece = n/size;//线程任务直角边长
//0号进程
if(myrank == 0)
{
init_matrix();
double t1, t2;
t1 = MPI_Wtime();
//0号进程转置
int q;
for(int ii=0;ii<piece;ii++)
{
for(int jj=ii+1;jj<piece;jj++)
{
q = matrix[ii][jj];
matrix[ii][jj] = matrix[jj][ii];
matrix[jj][ii] = q;
}
}
//向其他进程通信,分配任务
for(int i=1;i<size;i++)
{
int cnt = 0;
for(int a=0; a<n; a++){
for(int b=0; b<n; b++){
tmp[cnt] = matrix[a][b];
cnt++;
}
}
MPI_Send(tmp,n*n,MPI_INT,i,i,MPI_COMM_WORLD);
}
//向其他进程通信,接收结果
for(int i=1;i<size;i++)
{
MPI_Recv(tmp,n*n,MPI_INT,i,i,MPI_COMM_WORLD,&status);
int begin = i * piece; //确定线程的起始
int end = (i == size-1) ? n : begin + piece;//最后一个线程不管多少都包圆
for(int i=begin;i<end;i++)
{
for(int j=0;j<i;j++)
{
matrix[i][j] = tmp[i*n+j];
matrix[j][i] = tmp[j*n+i];
}
}
}
t2 = MPI_Wtime();
printf("time:%lf\n",t2-t1);
show_matrix(matrix);
delete matrix;
delete tmp;
}
// 其他进程转置自己的部分
else
{
MPI_Recv(tmp,n*n,MPI_INT,0,myrank,MPI_COMM_WORLD,&status);
int begin = myrank * piece; //确定线程的起始
int end = (myrank == size-1) ? n : begin + piece;//最后一个线程不管多少都包圆
// printf("%d\n", myrank);
// for(int i = 0; i<n; i++){
// for(int j = 0;j<n;j++){
// cout<<tmp[i*n+j]<<" ";}
// cout<<endl;}
// cout<<endl;
int t;
for(int i=begin;i<end;i++)
{
for(int j=0;j<i;j++)
{
t = tmp[i*n+j];
tmp[i*n+j] = tmp[j*n+i];
tmp[j*n+i] = t;
}
}
// printf("after %d\n", myrank);
// for(int i = 0; i<n; i++){
// for(int j = 0;j<n;j++){
// cout<<tmp[i*n+j]<<" ";}
// cout<<endl;}
// cout<<endl;
MPI_Send(tmp,n*n,MPI_INT,0,myrank,MPI_COMM_WORLD);
}
MPI_Finalize();
return 0;
}
并行计算前缀和:多线程技术模拟并行计算之二:数组前缀和(Prefix Sum)_忆之独秀的博客-CSDN博客_prefix sum
// *************************法一***************************************
#include<iostream>
#include<pthread.h>
#include<math.h>
using namespace std;
#define N 8 // 数组维度
int A[N] = {7,3,15,10,13,18,6,4};
int B[10][N]; //树,每一行是一层,第一维度>=log(N)即可
int prefix_sum[10][N]={0};
pthread_t tids[10][N];
pthread_mutex_t mutex;
struct S
{
int i ;
int j ;
};
//叶子节点并行赋值,即B第一行为A
void *func1(void *arg)
{
int i;
struct S *p;
p = (struct S*)arg;
i = p->i;
pthread_mutex_lock(&mutex);
B[0][i]=A[i];
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
return NULL;
}
// 并行对树从叶子节点两个两个求和得到上一层节点数
void *func2(void *args)
{
int h , j;
struct S *p;
p = (struct S*)args;
h = p->i;
j = p->j;
pthread_mutex_lock(&mutex);
B[h][j]=B[h-1][2*j-1]+B[h-1][2*j];
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
return NULL;
}
// 从上层向下传递并进行运算,得到前缀和
void *func3(void *arg)
{
int h,j;
struct S *p;
p = (struct S*)arg;
h = p->i;
j = p->j;
pthread_mutex_lock(&mutex);
if(j==1) prefix_sum[h][1] = B[h][1];
else if (j%2==0) prefix_sum[h][j] = prefix_sum[h+1][j/2] ;
else prefix_sum[h][j] = prefix_sum[h+1][(j-1)/2] + B[h][j] ;
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
return NULL;
}
int main()
{
int i,j,h;
for(i=1;i<=N;i++)
{
struct S *s;
s = (struct S *)malloc(sizeof(struct S));
s->i = i;
pthread_create(&tids[0][i],NULL,func1,s);
pthread_join(tids[0][i],NULL);
}
for(h=1;h<=log2(N);h++)
{
for(j=1;j<=N/pow(2,h);j++)
{
struct S *s;
s = (struct S*)malloc(sizeof(struct S));
s->i = h;
s->j = j;
pthread_create(&tids[h][j],NULL,func2,s);
pthread_join(tids[h][j],NULL);
}
}
for(h=log2(N);h>=0;h--)
{
for(j=1;j<=N/pow(2,h);j++)
{
struct S *s;
s = (struct S*)malloc(sizeof(struct S));
s->i = h;
s->j = j;
pthread_create(&tids[h][j],NULL,func3,s);
pthread_join(tids[h][j],NULL);
}
}
cout<<"The Prefix_sum is :"<<endl;
for(int i = 0;i<N;i++)
cout<<prefix_sum[0][i] + A[0]<<" ";
return 0;
}
// *************************法二***************************************
#include<iostream>
#include<pthread.h>
#include<math.h>
using namespace std;
#define N 8 // 数组维度
int A[N] = {7,3,15,10,13,18,6,4};
int prefix_sum[N]={0};
int temp[N]={0};
pthread_t tids[1000][1000];
pthread_mutex_t mutex;
struct S
{
int i ;
int j ;
};
void *func1(void *arg)
{
int i ;
struct S *p;
p = (struct S*)arg;
i = p->i;
pthread_mutex_lock(&mutex);
if(i==1) prefix_sum[i] = A[i];
else prefix_sum[i] = A[i-1] + A[i];
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
return NULL;
}
void *func2(void *arg)
{
int i ,k ;
struct S *p;
p = (struct S*)arg;
i = p->i;
k = p->j;
pthread_mutex_lock(&mutex);
temp[i] = prefix_sum[i-k] + prefix_sum[i];
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
return NULL;
}
int main()
{
int i,j,k;
for(i=1;i<=N;i++)
{
struct S* s;
s = (struct S*)malloc(sizeof(struct S));
s->i = i;
pthread_create(&tids[0][i],NULL,func1,s);
pthread_join(tids[0][i],NULL);
}
k=2;
while(k<N)
{
for(i=1;i<=N;i++)
temp[i] = prefix_sum[i];
for(i=k+1;i<=N;i++)
{
struct S* s;
s = (struct S*)malloc(sizeof(struct S));
s->i = i;
s->j = k;
pthread_create(&tids[k][i],NULL,func2,s);
pthread_join(tids[k][i],NULL);
}
for(i=1;i<=N;i++)
prefix_sum[i] = temp[i];
k = k + k;
}
cout<<"The Prefix_sum is :"<<endl;
for(int i = 0;i<N;i++)
cout<<prefix_sum[i] + A[0]<<" ";
return 0 ;
}