《多核程序設計》學習筆記:矩陣乘法並行化

說到矩陣乘法,最早想到的就是用兩個for循環,循環矩陣A的行再循環矩陣B的列,從而實現矩陣A與B的相乘。算法

(1)下面是串行算法的實現代碼:windows

#include<stdlib.h>
#include<stdio.h>
typedef struct
{
	int** mat;		//指向指針的指針
	int row,col;
}matrix;
void initial(matrix &M,int row,int col)  
{  
    int i,j = 0;  
    M.mat = (int **)malloc(row*sizeof(int *));		//分配列空間
    for (i = 0; i < row; i++)   
        M.mat[i] = (int *)malloc(col*sizeof(int));	//分配行空間
    M.row = row;  
    M.col = col;  
}
void initValue(matrix &M, int row, int col)  
{  
    int i, j;  
    initial(M,row,col);  
    for (i = 0; i < row; i++)  
    {  
		printf("請輸入第%d行的數據:",i);
        for (j = 0; j < col; j++)    
            scanf("%d",&M.mat[i][j]);  
    }  
} 
void Matrix_Multiply(matrix &A,matrix &B,matrix &C)
{
	int i,j,k;
	for(i=0;i<A.row;i++)	
	{
		for(j=0;j<B.col;j++)
		{
			C.mat[i][j]=0;		//矩陣C須要初始化爲0,不然會輸出負值
			for(k=0;k<B.row;k++)
				C.mat[i][j]+=A.mat[i][k]*B.mat[k][j];
		}
	}
}
void main()
{
	matrix A,B,C;
	int row_a,col_a,row_b,col_b;
	printf("請輸入矩陣A的行數,列數:");
	scanf("%d,%d",&row_a,&col_a);
	printf("請輸入矩陣B的行數,列數:");
	scanf("%d,%d",&row_b,&col_b);
	if(row_a<0||col_a<0||row_b<0||col_b<0||col_a!=row_b)
		printf("輸入數據有誤!");
	else
	{
		printf("矩陣A初始化\n");
		initValue(A,row_a,col_a);
		printf("矩陣B初始化\n");
		initValue(B,row_b,col_b);
		initial(C,row_a,col_b);
		Matrix_Multiply(A,B,C);
		printf("矩陣A*B的結果:\n");
		for(int i=0;i<C.row;i++)
		{
			for(int j=0;j<C.col;j++)
				printf("%d ",C.mat[i][j]);
			printf("\n");
		}
	}
}

(2)並行算法採用的是咱們在計算時常用的行列相乘法,即把將A按行(A1 A2......)分配到A.row個處理器上,後是經過B(B1 B2......)的移位從而實現A的每一行與B的每一列相乘,從而實現並行化並行算法的實現代碼:線程

//#include"stdafx.h"
#include<stdlib.h>
#include<stdio.h>
#include<windows.h>
typedef struct
{
	int** mat;		//指向指針的指針
	int row,col;
}matrix;
typedef struct
{
	int	a;		//A的行數
	int b;		//B的列數
}parameter;
matrix A,B,C;
HANDLE* h=(HANDLE* )malloc(sizeof(HANDLE)*A.row);
void initial(matrix &M,int row,int col)  
{  
    int i,j = 0;  
    M.mat = (int **)malloc(row*sizeof(int *));		//分配列空間
    for (i = 0; i < row; i++)   
        M.mat[i] = (int *)malloc(col*sizeof(int));	//分配行空間
    M.row = row;  
    M.col = col;  
}
void initValue(matrix &M, int row, int col)  
{  
    int i, j;  
    initial(M,row,col);  
    for (i = 0; i < row; i++)  
    {  
		printf("請輸入第%d行的數據:",i);
        for (j = 0; j < col; j++)    
            scanf("%d",&M.mat[i][j]);  
    }  
} 
void Multiply(void *n)		//i是A的行數
{
	int i;
	parameter p=*((parameter *)n);
	C.mat[p.a][p.b]=0;
	for(i=0;i<A.col;i++)
	{
		C.mat[p.a][p.b]+=A.mat[p.a][i]*B.mat[i][p.b];	
	}
}
void Parallel_MatrixMultiply(matrix &A,matrix &B,matrix &C)
{
	int i,j;
	parameter* p=(parameter* )malloc(sizeof(parameter)*A.row);
	int *tag=(int* )malloc(sizeof(int)*A.row);
	for(i=0;i<B.col;i++)
		tag[i]=i;
	for(i=0;i<B.col;i++)
	{
		for(j=0;j<A.row;j++)
		{
			p[j].a=j;
			p[j].b=tag[(i+j)%A.row];		//B移位的過程
			h[j]=CreateThread(NULL,			//建立A.row個線程
							0,
							(LPTHREAD_START_ROUTINE)Multiply,
							&p[j],		//不能直接傳i
							0,
							NULL);
			printf("建立線程\n");
		}
	}
}
void main()
{
	int row_a,col_a,row_b,col_b;
	printf("請輸入矩陣A的行數,列數:");
	scanf("%d,%d",&row_a,&col_a);
	printf("請輸入矩陣B的行數,列數:");
	scanf("%d,%d",&row_b,&col_b);
	if(row_a<0||col_a<0||row_b<0||col_b<0||col_a!=row_b)
		printf("輸入數據有誤!");
	else
	{
		printf("矩陣A初始化\n");
		initValue(A,row_a,col_a);
		printf("矩陣B初始化\n");
		initValue(B,row_b,col_b);
		initial(C,row_a,col_b);
		Parallel_MatrixMultiply(A,B,C);
		WaitForMultipleObjects(A.row,h,TRUE,INFINITE);
		printf("矩陣A*B的結果:\n");
		for(int i=0;i<C.row;i++)
		{
			for(int j=0;j<C.col;j++)
				printf("%d ",C.mat[i][j]);
			printf("\n");
		}
	}}
相關文章
相關標籤/搜索