说到矩阵乘法,最先想到的就是用两个for循环,循环矩阵A的行再循环矩阵B的列,从而实现矩阵A与B的相乘。
(1)下面是串行算法的实现代码:
#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");
}
}}