并行计算实验

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 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值