问题引入:

主体思路:(为了尽可能使计算简便,所有的实验矩阵均是方阵)

1.    对于A,B矩阵,首先根据子进程数p将其划分成p块形式相同的小矩阵块,其中每个矩阵块只要求是方阵即可,具体可以是1阶的,2阶的或n阶的。这里的子进程数p我采用了用于具体计算的进程数量,即除0进程以外的所有进程。划分完毕后,每个进程都持有矩阵A与矩阵B对应位置的一对儿分块阵。

2.    对A,B矩阵进行初始位置分配,这里不好用语言描述,下面三阶分块阵为例,给出示意图(因为二阶分块阵在课件中已经给出且不具一般性):

对于矩阵A

一个箭头表示移动一次,方向为左,移动完成后为

对于矩阵B

一个箭头表示移动一次,方向为上,移动完成后为

A,B位置初始化完成后,对应位置分块阵相乘,重新组合成的矩阵为C0

之后,【矩阵A所有行按上述规则左移一次,B的所有列上移一次,再对应相乘相加,得到矩阵C1】,重复步骤【】p-1次,依次得到C1,C2,,,Cn

对于上述三阶分块阵来说,将得到的C0,C1,C2相加即为所求。

各个子进程将自己求得的矩阵C的分块阵发送给进程0,汇总后即为最后的矩阵C。

程序部分关键代码(非完整)如下:

1 二维数组创建函数:

int **create_array(int row, int column, int flag, int rank)

row:行数,column:列数

flag:为1创建随机数数组,为0创建全0数组

rank:进程号,可有可无,这里用来简单的保证每个进程产生的数组不一样(进程号不一样)

2 关键变量说明:

int num_block = sqrt(size-1);        //order of sub-blocks
int order_submatrix = 4 / num_block; // order of per sub-block, 4 means 4 order square matrix, also can be 9, 16,,,
int compute_times = num_block - 1;   // compute times after the initially moved

3 A位置初始化:

//*********************************Initial matrixA  positionif(rank > num_block ){                  // limit to second row at leastint dest_A = (rank > num_block && rank % num_block == 1) ? rank + num_block - 1 : rank - 1;int source_A = (rank > num_block && rank % num_block == 0) ? rank - num_block + 1 : rank + 1;int move_times_row = (rank - 1) / num_block;    // move times per rowwhile(move_times_row--){for(i=0; i<order_submatrix; i++)for(j=0; j<order_submatrix; j++)sbuf[i * order_submatrix + j] = matrixA[i][j];    //write data to senfbufif(rank % order_submatrix == 1){MPI_Ssend(sbuf, order_submatrix*order_submatrix, MPI_INT, dest_A, 1, MPI_COMM_WORLD);MPI_Recv(rbuf, order_submatrix*order_submatrix, MPI_INT, source_A, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);for(i=0; i<order_submatrix; i++)for(j=0; j<order_submatrix; j++)matrixA[i][j] = rbuf[i * order_submatrix + j];}else{MPI_Recv(rbuf, order_submatrix*order_submatrix, MPI_INT, source_A, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);for(i=0; i<order_submatrix; i++)for(j=0; j<order_submatrix; j++)matrixA[i][j] = rbuf[i * order_submatrix + j];MPI_Ssend(sbuf, order_submatrix*order_submatrix, MPI_INT, dest_A, 1, MPI_COMM_WORLD);}       //else}       //while}       //if

几个关键的地方都有注释,不再赘述。注意以下几个问题:

  1. 每行分块阵移动必须形成闭环,为了避免闭环资源竞争,每行第一个块(也即拥有此矩阵的进程)需单独考虑,用同步的方式先发送再接收,其他的先接收再发送。
  2. 确定dest时单独考虑每行第一个,确定source时单独考虑每行最后一个。
  3. 注意哪行移动,移动几次。
  4. 二维数组以一维方式发送和接收,处理起来非常简单。

4 B位置初始化:

原理同A,不放代码,自行思考。

5 C的初始化

 //********************************compute the matrixC's initial position ---- C_0for(i=0; i<order_submatrix; i++){for(j=0; j<order_submatrix; j++){for(k=0; k<order_submatrix; k++)matrixC[i][j] += matrixA[i][k] * matrixB[k][j];}}

就是A与B乘法计算,然后存到C对应位置

6 对A全部行循环左移:

while(compute_times--){同上述方式进行数据传送}

7 对B全部列循环上移:

//****************shift all columns of matrixB onceint dest_B = (rank <= num_block) ? rank + (num_block - 1) * num_block : rank - num_block;int source_B = (rank > (num_block - 1) * num_block) ? rank - (num_block - 1) * num_block : rank + num_block;for(i=0; i<order_submatrix; i++)for(j=0; j<order_submatrix; j++)sbuf[i * order_submatrix + j] = matrixB[i][j];if(rank <= num_block){MPI_Ssend(sbuf, order_submatrix*order_submatrix, MPI_INT, dest_B, 2, MPI_COMM_WORLD);MPI_Recv(rbuf, order_submatrix*order_submatrix, MPI_INT, source_B, 2, MPI_COMM_WORLD, MPI_STATUS_IGNORE);for(i=0; i<order_submatrix; i++)for(j=0; j<order_submatrix; j++)matrixB[i][j] = rbuf[i * order_submatrix + j];}else{MPI_Recv(rbuf, order_submatrix*order_submatrix, MPI_INT, source_B, 2, MPI_COMM_WORLD, MPI_STATUS_IGNORE);for(i=0; i<order_submatrix; i++)for(j=0; j<order_submatrix; j++)matrixB[i][j] = rbuf[i * order_submatrix + j];MPI_Ssend(sbuf, order_submatrix*order_submatrix, MPI_INT, dest_B, 2, MPI_COMM_WORLD);}       //else

跟B初始化一样,但上面没说,这里就放一下代码,,,记得外面套个一起放到6的while大循环里,具体要单独考虑谁参考3分析

8 C的累加

上面6 和 7是一起的,同时每移动一次就要计算移动完后A与B的乘法,加上C,再对C的对应位置覆盖,就是 C += C + A * B的形式,这儿不写了。

9 数据汇总

 MPI_Gather(sbuf, order_submatrix * order_submatrix, MPI_INT, rbuf, order_submatrix * order_submatrix, MPI_INT, 0, MPI_COMM_WORLD);if(rank == 0){//    输出格式处理,数据都放在rbuf里了,注意与这是矩阵块的顺序+小矩阵元素顺序,不是最后大矩阵的顺序}    //if    

这一部之前进程0还一直没用呢,发现没?其实这样不太好,,,管他呢。

Gather调用数据发给0进程,格式处理我就不管了

10 结果:

$mpicc -o 2Dmatrix 2Dmatrix.c -lm             // parameter -lm for math.h

$ mpiexec -n 5 ./2Dmatrix

process 1 matrix A:
4 7 
8 6 
process 1 matrix B:
8 10 
11 7 
process 2 matrix A:
5 8 
9 7 
process 2 matrix B:
9 11 
12 8 
process 3 matrix A:
6 9 
10 8 
process 3 matrix B:
10 12 
13 9 
process 4 matrix A:
7 10 
11 9 
process 4 matrix B:
11 13 
14 10

the final matrixC in process 0 is :

263 221 
311 293 
 ^^ sub-block 1 is : 
287 245 
341 323 
 ^^ sub-block 2 is : 
347 297 
395 369 
 ^^ sub-block 3 is : 
379 329 
433 407

^^ sub-block 4 is :

这是以4阶方阵,2阶分块阵,4个计算子进程(算上0进程5个)为例的,可以随意拓展成n阶分块阵,n^2个计算子进程,至于实际方阵阶数,随意1阶,2阶,3阶,,,保证每个小块是方的就行。

总结

程序原理比较简单,实现也不麻烦,基本真正思考的只有1/4,剩下的都直接复制改改就好,比如对A的行的思考跟B的列的思考差不多一样的。我认为难点只有一个,即从题目中二阶到三阶的数学推倒,题目表述不清且二阶太简单找不到规律,干瞪眼半天不会,不失一般性,写到三阶,一下子都明白了。

MPI并行程序-矩阵分块乘法( Matrix multiplication : Two-Demension Method)相关推荐

  1. c语言mpi并行程序,高性能计算之并行编程技术MPI并行程序设计(完整版).pdf

    高性能计算之并行编程技术MPI并行程序设计(完整版) 高性能计算之并行编程技术 -- MPI并行程序设计 都志辉 编著 李三立 审阅 陈渝 刘鹏 校对 I 内容提要 本书介绍目前最常见的并行程序- M ...

  2. MPI并行程序编写与调试(奇偶变换排序)

    MPI并行程序编写与调试(奇偶变换排序) 一.编写MPI并行计算程序 奇偶排序在多线程进行计算代码如下: 关于奇偶排序这里不做过多描述. /** File: mpi_odd_even.c* Purpo ...

  3. MPI并行编程: 矩阵乘法,积分计算,PSPR排序

    简介 MPI(Message-Passing-Interface 消息传递接口)实现并行是进程级别的,通过通信在进程之间进行消息传递.MPI并不是一种新的开发语言,它是一个定义了可以被C.C++和Fo ...

  4. MPI并行程序的调试技巧

    原文地址:http://galoisplusplus.gitcafe.com/blog/2013/06/08/mpi-debug-tips/ debug一个并行程序(parallel program) ...

  5. c语言mpi并行程序,[转]MPI并行程序的调试技巧

    debug一个并行程序(parallel program)向来是件很麻烦的事情(Erlang等functional programming language另当别论),对于像MPI这种非shared ...

  6. MPI并行程序开发设计----------------------------------并行编程模型和算法等介绍

    ---------------------------------------------------------------------------------------------------- ...

  7. c语言mpi矩阵乘法,【MPI并行程序】矩阵乘法

    具体思路为创建矩阵,给每个进程分配矩阵的不同部分,每个进程根据进程号的不同处理矩阵的不同部分,计算完成后将每个进程的数组发送给一个特定的进程,由该进程合成一个完整的矩阵输出出来.问题是不一定每个进程都 ...

  8. 【MPI学习3】MPI并行程序设计模式:不同通信模式MPI并行程序的设计

    学习了MPI四种通信模式 及其函数用法: (1)标准通信模式:MPI_SEND (2)缓存通信模式:MPI_BSEND (3)同步通信模式:MPI_SSEND (4)就绪通信模式:MPI_RSEND ...

  9. Element-wise Multiplication and Matrix Multiplication

    Element-wise Multiplication and Matrix Multiplication 一. Element-wise Multiplication:在python通过 *实现 1 ...

最新文章

  1. MediaCodeC解码视频指定帧,迅捷、精确
  2. 月薪没过20K的程序员要注意了!(文末送书)
  3. 20个开源项目托管站点推荐
  4. codeforces831c 思维
  5. dicom文件_DICOM数据转成NIfTI数据
  6. sql2000 中 存储过程 相关
  7. Product Overview page data loss handling
  8. Tailwind CSS 是一个工具集 CSS 框架
  9. [剑指offer][JAVA][第62题][约瑟夫环][LinkedList vs ArrayList]
  10. 安装部署gitlab ci
  11. VS2017安装或卸载错误1303
  12. tcpdump抓包最常用的命令
  13. PHP正则表达式(是)
  14. RuntimeError: view size is not compatible with input tensor‘s size and stride
  15. Git简洁教程:本地项目如何与GitHub互连
  16. Dataframe中添加一列
  17. springboot vue3 elementui plus小说阅读网站源码
  18. 动态网站如何生成静态页面
  19. 结构建模设计——Solidworks软件之草图绘制基础图形工具总结(绘制直线、矩形、圆、槽、圆弧、圆角等)
  20. [Python 高德地图] API调用学习历程(一)

热门文章

  1. 惠普屏幕录制,截屏的快捷键
  2. 葛兰岱尔3D/BIM/GIS轻量化引擎直接支持PTC Creo和Siemens Nx软件
  3. ArcGIS Pro发布三维服务操作流程
  4. 于剑《机器学习》复习总结
  5. 北洋标签打印机BTP-2100E安装(usb转并口)
  6. 超级形缺工具20211226版
  7. 苹果之前删除计算机怎么恢复,苹果电脑删除的文件怎么找回?
  8. linux 弹出usb设备,linux安全移除USB设备
  9. linux命令之poweroff
  10. python人工智能项目实例-Python在人工智能中的实例