矩阵乘法

1. 需求

矩阵乘法AB=C。其中,A,B,C均为20482048双精度浮点方阵,A,B初始值为[-1,1]的随机数。

2.串行和OpenMP并行代码

#include <iostream>
#include <stdlib.h>
#include <ctime>
#include "hpc_helpers.hpp"
using namespace std;
#define NUM 2048    //表示数组的长度
//由于数组过大,所以需要定义全局变量,否则容量不够
double A[NUM][NUM];
double B[NUM][NUM];
double C[NUM][NUM];//初始化
void init (double A[][NUM] , double B[][NUM]) {srand ((unsigned int)time (NULL));for ( int row = 0; row < NUM; row++ ) {for ( int col = 0; col < NUM; col++ ) {//x + 1.0 * rand() / RAND_MAX * ( y - x )//随机生成[-1,1]的随机双精度浮点数A[row][col] = -1.0 + 1.0 * rand () / RAND_MAX * 2;A[row][col] = -1.0 + 1.0 * rand () / RAND_MAX * 2;}}
}//计算(矩阵乘法)
void mult (double A[][NUM] , double B[][NUM] , double C[][NUM] , bool parallel , int num_thread) {
#pragma omp parallel for num_threads(num_thread)if(parallel)//使用三重for循环完成矩阵的乘法for ( int i = 0; i < NUM; i++ ) {   //完成行结果的循环(相对结果C矩阵)for ( int j = 0; j < NUM; j++ ) {    //完成列结果的循环(相对结果C矩阵)double accum = 0;for ( int k = 0; k < NUM; k++ ) {  //最内层循环,负责完成A的行乘以B的列//A的第i行的数分别乘以B的第j列的相应数,即矩阵乘法(k表示“相应数”的位置)accum += A[i][k] * B[k][j];}C[i][j] = accum;}}
}
int main () {TIMERSTART (overall)   //计算花费的总时间cout << "=========初始化花费时间=========" << endl;//计算初始化花费的时间TIMERSTART (init)init (A , B);    //初始化TIMERSTOP (init)cout << "=========串行花费时间=========" << endl;//计算3次串行花费的时间for ( int i = 0; i < 3; i++ ) {TIMERSTART (mult_seq)mult (A , B , C , false , 1);TIMERSTOP (mult_seq)}//计算3次并行花费的时间(分别2、4、8、16、32线程)for ( int i = 2; i < 33;i=i*2) {cout << "=========并行花费时间=========" << endl;cout << "当前线程数:" << i << endl;for ( int j = 0; j < 3; j++ ) {TIMERSTART (mult_par)mult (A , B , C , true , i);TIMERSTOP (mult_par)}}TIMERSTOP (overall)return 0;
}

代码分析:

首先,引入了一个定制的头文件hpc_helpers.hpp用于测量程序各部分的时间花销。因为涉及的二维数组比较大(2048*2048),所以需要将所用数组定义为全局变量,否则会因为栈容量不够而报错。

其次,将数组的初始化封装为init函数,其中会将数组以随机双精度浮点数初始化,随机数的范围是[-1,1]。而矩阵乘法的关键计算部分被封装为mult函数,其中将利用三重for循环实现矩阵乘法,程序的“并行”代码是‘#pragma omp parallel for num_threads(num_thread)if(parallel)’。mult函数中的参数parallel (bool)用于在串行和并行执行模式之间切换,参数num_thread(int)则是设置程序并行运行时的线程数。

最后,以同一份数据分别执行并行模式下的2、4、8、16、32个线程情况。同时,为了保证实验数据的可靠性,程序将会把随机生成的矩阵分别计算三次(串行和并行),并且打印出每次计算的时间花销。

性能分析

图1显示了分别在串行模式和并行模式(2、4、8、16、32个线程)运行的时间花销,其中,elapsed time (init)表示初始化花费的时间,elapsed time (mult_­seq) 表示串行模式花费的时间,elapsed time (mult_­par) 表示并行模式下花费的时间,elapsed time (overall)表示程序总共花费的时间。
​ 图 1 程序运行结果截图
图2为程序运行时cpu线程数和运行窗口的截图,显示了程序设置的运行时线程数与系统分配给程序的线程数是匹配的。

​ 图 2 系统线程数截图
由图1可总结出表格1。

**线程数P/** 平均花销时间T/s 加速比S 相应并行效率E
1**(串行)** 61.93 / /
2 32.58 1.90 95%
4 18.46 3.35 84%
8 9.76 6.35 80%
16 5.91 10.48 66%
32 5.96 10.39 32%


​ 图 3 加速比曲线图
由表格1和图3可知,程序的加速比随着线程数的增加而增大,其原因在于更大数目的线程数需要更多的额外通信开销,相应的并行效率随着线程数的增加而减小。同时,注意到线程数为32时,加速比反而是略微下降。原因可能是实验的笔记本电脑cup为8核16线程,而一般并行设置的线程数最大为(核心数*2-1),所以当线程数为32时导致的电脑卡顿从而增加了时间。

矩阵乘法(串行与并行)相关推荐

  1. 技能梳理37@stm32+按键+光耦+锁存+串行转并行+继电器

    技能梳理37@stm32+按键+光耦+锁存+串行转并行+继电器 1.项目简介 2.实现逻辑 3.应用场景 #主从机有线控制 #开关操作 4.核心代码梳理 //根据按下的按键执行相应的操作 void h ...

  2. 高性能计算实验——矩阵乘法基于MPI的并行实现及优化

    高性能计算实验--矩阵乘法基于MPI的并行实现及优化 1.实验目的 1.1.通过MPI实现通用矩阵乘法 1.2.基于MPI的通用矩阵乘法优化 1.3.改造实验1成矩阵乘法库函数 2.实验过程和核心代码 ...

  3. 同步、异步 与 串行、并行的区别

    同步.异步: 指的是能否开启新的线程.同步不能开启新的线程,异步可以. 串行.并行: 指的是任务的执行方式.串行是指多个任务时,各个任务按顺序执行,完成一个之后才能进行下一个.并行指的是多个任务可以同 ...

  4. java sync和async区别_GCD中串行、并行与async、sync的区别

    * author:conowen@大钟 * E-mail:conowen@hotmail.com 队列由一个或多个任务组成,当这些任务要开始执行时,系统会分别把他们分配到某个线程上去执行. 串行队列. ...

  5. 串行测试 并行测试_如何通过CircleCI测试并行性增加构建时间

    串行测试 并行测试 by Karel Rochelt 卡雷尔·罗切尔特(Karel Rochelt) 如何通过CircleCI测试并行性增加构建时间 (How to boost build time ...

  6. AsyncTask——AsyncTask串行and并行

    一.前言 AsyncTask,相信你不会陌生,也许你很幸运,早已了解了AsyncTask这个家伙挖的坑,也许你已经被坑过了,也许你没坑了,然而还没有发觉. 本次笔者将带大家一起来看下AsyncTask ...

  7. 串行、并行、并发,别再傻傻分不清了!

    开足码力,码动人生,微信搜索[ 程序员大帝 ],关注这个一言不合就开车的的代码界老司机 本文 GitHub上已经收录 https://github.com/BeKingCoding/JavaKing ...

  8. 并发、并行、同步、异步、进程,线程、串行、并行?一文弄懂八大概念

    并发.并行.同步.异步.进程,线程.串行.并行?一文弄懂八大概念 参考博文:并发.并行.串行.同步.异步的区别? java多线程详解(并发,并行,同步) 文章目录 并发.并行.同步.异步.进程,线程. ...

  9. 串行测试 并行测试_什么是并行测试,为什么要采用它?

    串行测试 并行测试 随着技术的进步,随着组织从手动测试转向Selenium测试自动化 ,测试解决方案变得比以往更具可扩展性. 但是,大多数组织仍在努力的领域之一是可并行运行多个测试的可伸缩性. 许多公 ...

最新文章

  1. 什么,PyTorch还能开发新药?哈佛推出这款工具包,10行代码训练“药神”模型...
  2. phpcms V9利用num++实现多样形式列表标签调用
  3. 软件测试2019:第二次作业
  4. 网络验证常见的攻击方式与防御手段
  5. C# 值类型与引用类型(1)
  6. 【Codeforces】925A Stairs and Elevators【贪心】
  7. 设置X轴,y轴分格线,使用对象句柄完成
  8. mips的旁路_低功耗设计二之Bypassing(旁路)
  9. 【二极管】稳压二极管全面分析
  10. 495. Teemo Attacking(提莫攻击)
  11. 从事前端开发如何提升自我能力?
  12. HDU 4372 Count the Buildings [第一类斯特林数]
  13. NYOJ 62 笨小熊
  14. 关于电脑显示器分辨率只有两个选项1024×768和800×600的解决办法,本人电脑亲测可用
  15. MySQL Group Replication的RECOVERING状态深度理解
  16. Qt焦点事件 setFocusPolicy
  17. LeetCode 51-60题
  18. 各个等级测试工程师所需的必要技能
  19. 数学建模准备 插值(拉格朗日多项式插值,牛顿多项式插值,分段线性插值,分段三次样条插值,分段三次Hermite插值)
  20. Google优化排名方法

热门文章

  1. 【学习笔记】Dubbo学习_黑马程序员_随记_2023.1.26
  2. 百度智能云 × 酷开网络 | 让电视回归电视的智能秘诀
  3. 国外的街头3D艺术与咱自家的街头3D艺术
  4. CodeForces 997 简要题解
  5. Java Stream来写算法10——毕达哥拉斯Pythagoras——勾股定理数
  6. Python爬虫自学笔记(五)Scrapy框架
  7. 用wordpress打造的第一个小程序:图书共享借阅
  8. 四川师范大学何云:事项法会计从五大方面助力企业创造价值
  9. 关于可变参数函数+ _INTSIZEOF宏实现详细
  10. 频繁弹出找到新硬件向导