并行计算-实验二-矩阵乘法的OpenMP实现及性能分析

合集下载

华科并行实验报告

华科并行实验报告

一、实验模块计算机科学与技术二、实验标题并行计算实验三、实验目的1. 了解并行计算的基本概念和原理;2. 掌握并行编程的基本方法;3. 通过实验加深对并行计算的理解。

四、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 并行计算平台:OpenMP五、实验步骤1. 准备实验环境首先,在计算机上安装OpenMP库,并配置环境变量。

2. 编写并行计算程序编写一个简单的并行计算程序,实现以下功能:(1)计算斐波那契数列的第n项;(2)计算素数的个数;(3)计算矩阵乘法。

以下为斐波那契数列的并行计算程序示例:```cpp#include <omp.h>#include <iostream>using namespace std;int main() {int n = 30;int fib[31] = {0};fib[0] = 0;fib[1] = 1;#pragma omp parallel forfor (int i = 2; i <= n; i++) {fib[i] = fib[i - 1] + fib[i - 2];}cout << "斐波那契数列的第" << n << "项为:" << fib[n] << endl; return 0;}```3. 编译程序使用g++编译器编译程序,并添加OpenMP库支持。

```bashg++ -fopenmp -o fib fib.cpp```4. 运行程序在命令行中运行编译后的程序,观察结果。

5. 分析结果通过对比串行计算和并行计算的结果,分析并行计算的优势。

六、实验过程1. 准备实验环境,安装OpenMP库并配置环境变量;2. 编写并行计算程序,实现斐波那契数列的并行计算;3. 编译程序,并添加OpenMP库支持;4. 运行程序,观察结果;5. 分析结果,对比串行计算和并行计算的性能。

并行程序设计实验报告-OpenMP 进阶实验

并行程序设计实验报告-OpenMP 进阶实验

实验2:OpenMP 进阶实验1、实验目的掌握生产者-消费者模型,具备运用OpenMP相关知识进行综合分析,可实现实际工程背景下生产者-消费者模型的线程级负责均衡规划和调优。

2、实验要求1)single与master语句制导语句single 和master 都是指定相关的并行区域只由一个线程执行,区别在于使用master 则由主线程(0 号线程)执行,使用single 则由运行时的具体情况决定。

两者还有一个区别是single 在结束处隐含栅栏同步,而master 没有。

在没有特殊需求时,建议使用single 语句。

程序代码见程序2-12)barrier语句在多线程编程中必须考虑到不同的线程对同一个变量进行读写访问引起的数据竞争问题。

如果线程间没有互斥机制,则不同线程对同一变量的访问顺序是不确定的,有可能导致错误的执行结果。

OpenMP中有两种不同类型的线程同步机制,一种是互斥机制,一种是事件同步机制。

其中事件同步机制的设计思路是控制线程的执行顺序,可以通过设置barrier同步路障实现。

3)atomic、critical与锁通过critical 临界区实现的线程同步机制也可以通过原子(atomic)和锁实现。

后两者功能更具特点,并且使用更为灵活。

程序代码见程序2-2、2-3、2-44)schedule语句在使用parallel 语句进行累加计算时是通过编写代码来划分任务,再将划分后的任务分配给不同的线程去执行。

后来使用paralle for 语句实现是基于OpenMP 的自动划分,如果有n 次循环迭代k 个线程,大致会为每一个线程分配[n/k]各迭代。

由于n/k 不一定是整数,所以存在轻微的负载均衡问题。

我们可以通过子句schedule 来对影响负载的调度划分方式进行设置。

5)循环依赖性检查以对π 的数值估计的方法为例子来探讨OpenMP 中的循环依赖问题。

圆周率π(Pi)是数学中最重要和最奇妙的数字之一,对它的计算方法也是多种多样,其中适合采用计算机编程来计算并且精确度较高的方法是通过使用无穷级数来计算π 值。

矩阵乘法的并行化实验报告

矩阵乘法的并行化实验报告

北京科技大学计算机与通信工程学院实验报告实验名称:学生姓名:专业:班级:学号:指导教师:实验成绩:________________________________实验地点:实验时间:2015年05月一、实验目的与实验要求1、实验目的1对比矩阵乘法的串行和并行算法,查看运行时间,得出相应的结论;2观察并行算法不同进程数运行结果,分析得出结论;2、实验要求1编写矩阵乘法的串行程序,多次运行得到结果汇总;2编写基于MPI,分别实现矩阵乘法的并行化。

对实现的并行程序进行正确性测试和性能测试,并对测试结果进行分析。

二、实验设备(环境)及要求《VS2013》C++语言MPICH2三、实验内容与步骤实验1,矩阵乘法的串行实验(1)实验内容编写串行程序,运行汇总结果。

(2)主要步骤按照正常的矩阵乘法计算方法,在《VS2013》上编写矩阵乘法的串行程序,编译后多次运行,得到结果汇总。

实验2矩阵乘法的并行化实验3个总进程5个总进程7个总进程9个进程16个进程四:实验结果与分析(一)矩阵乘法并行化矩阵并行化算法分析:并行策略:1间隔行带划分法算法描述:将C=A*B中的A矩阵按行划分,从进程分得其中的几行后同时进行计算,最后通信将从进程的结果合并的主进程的C矩阵中对于矩阵A*B如图:进程1:矩阵A第一行进程2:矩阵A第二行进程3:矩阵A第三行进程1:矩阵A第四行时间复杂度分析:f(n) =6+2+8+k*n+k*n+k*n+3+10+n+k*n+k*n+n+2(k为从进程分到的行数)因此O(n)=(n);空间复杂度分析:从进程的存储空间不共用,f(n)=n;因此O(n)=(n);2间隔行带划分法算法描述:将C=A*B中的A矩阵按行划分,从进程分得其中的几行后同时进行计算,最后通信将从进程的结果合并的主进程的C矩阵中对于矩阵A*B如图:进程1:矩阵A第一行进程2:矩阵A第二行进程3:矩阵A第三行进程3:矩阵A第四行时间复杂度分析:f(n) =6+2+8+k*n+k*n+k*n+3+10+n+k*n+k*n+n+2(k为从进程分到的行数)因此O(n)=(n);空间复杂度分析:从进程的存储空间不共用,f(n)=n;因此T(n)=O(n);测试环境简介:《VS2013》Win7旗舰版正确性测试结果:并行结果:串行结果:通过比较发现两者相同,因此可以确定运算结果正确。

并行计算系统中的矩阵乘算法及其MPI实现

并行计算系统中的矩阵乘算法及其MPI实现


要 : 绍 了 MP 并 行 机 群 环 境 以及按 行 划 分矩 阵乘 算 法 和 按 行 列 划 分 矩 阵 乘 算 法 2种 算 法 , 析 了这 2种 矩 介 I 分
阵乘划分算法时间开销 的长短 , 并通过 MP 编程在 M I I P 并行机 群环境 下得 到 了实现 , 通过 实验得 到: 50X 0 在 0 0 5 规模的矩阵乘运算 中, 按行划分矩阵乘算法的 时问开销对矩阵乘并行计 算效 率的影响要 大于按 行列划分矩 阵乘 算
群 系统 的搭 建 需 要 使 用 相 应 的并 行 编程 环 境 。 目 前 并行编 程环 境 主 要 有并 行 虚拟 计 算 机 P M(a— V pr a e vta m cie , 息 传 递 接 口 MP ( sae ll iul ahn ) 消 l r I mesg
p si t fc ) E pesP Zpo e等 , 中 P M as gi e ae ,x rs,4,icd n nr 其 V
本文 以 MP 并行 机 群环 境 为基 础 , I 首先 介 绍 按
设 备 和操作 系统 , 它 们 工 作 时就 像 一个 统 一 的整 但 体, 各个 工作站 在并行 环境 下协调 工作 J 。
行划 分矩 阵乘算法 和按行 列划 分矩 阵乘算法 2种算
法, 然后分 析按行 划 分矩 阵乘 算 法 和按 行列 划 分 矩
成 为一种 单 一 的计 算 资源 来 使 用 的 系 统 。并 行 机
计算 机体 系结构 , 随着 微 处理 器 技 术 和计 算 机互 是 连 网络技术 的迅 速发 展 而 出现 的 , 实 现并 行 计算 是
的一 种新 主流技术 , 属于 分 布式 存 储 的并 行 计算 机 结构 , 型的机 群 系统结 构如 图 1 示 。机 群 系统 典 所

OpenMP的应用与实现

OpenMP的应用与实现

OpenMP的应用与实现OpenMP的应用与实现随着计算机技术的不断发展,程序员们需要在更短的时间内开发出更高效、更快速的程序,以满足现代科学和工程领域对计算的需求。

在多核处理器和集群系统的背景下,一种新的编程技术——OpenMP,应运而生。

OpenMP为C、C++和Fortran等语言提供了一种简单而有效的方式来并行化应用程序,可显著加速程序的执行速度。

本文将介绍OpenMP的应用与实现。

一、OpenMP的基本概念OpenMP是一种可移植、可扩展的共享内存并行编程技术,被广泛用于高性能计算应用中。

它可以在现有的串行代码中添加共享内存并行性,从而提高程序的效率。

OpenMP采用指令集合作,程序员可以通过在应用程序中添加特定的OpenMP指令,来控制并行执行的细节。

这些指令将告诉编译器如何将串行代码并行化。

OpenMP的并行模型是基于线程的共享内存模型。

线程是程序执行的最小单元,可以实现不同的计算任务同时运行。

OpenMP使用共享内存模型,即多个线程可以访问同一块内存,从而实现数据的共享。

为了保证数据的安全性,OpenMP提供了同步机制,可以保证共享资源的一致性和正确性。

二、OpenMP指令OpenMP定义了一系列指令,用于控制多线程的创建、同步和运行。

下面是一些常用的OpenMP指令:1. #pragma omp parallel该指令用于创建一个并行区域。

在这个区域内所有指令都会被多个线程执行。

当线程遇到这个指令时,会创建一个线程队列,然后每个线程会执行这个指令块内的内容。

2. #pragma omp for该指令用于循环并行化。

在多核处理器或者集群系统中,循环的迭代次数可以分配给不同的线程来并行执行,从而加速程序的执行速度。

3. #pragma omp sections该指令用于将代码分成多个段,每个段可以由不同的线程执行。

4. #pragma omp critical该指令用于保证在同一时间只有一个线程可以执行指定的代码块。

并行处理实验:矩阵乘法的加速比性能分析,用MPI实现源代码

并行处理实验:矩阵乘法的加速比性能分析,用MPI实现源代码

DenseMulMatrixMPI.c#include <stdio.h>#include <stdlib.h>#include <mpi.h>#include <time.h>//#include <windows.h>#define Length 1000int *A,*B,*C;//A、B、C一维数组分别记录矩阵A、B、C,以行优先的方式存储int *buffer,*ans;int temp;//临时变量,存储乘法过程中的中间值double startTime,endTime,totalTime;//startTime endTime totalTime分别表示矩阵乘之前的时间、之后的时间,以及矩阵乘所花费的时间int procsID,procsNum;//进程标识、进程个数int i,j,k;int line;//每个进程可以分配的矩阵行数//初始化矩阵/*void InitMatrix(int *M,int len){//产生0到49之间的随机数//int count=0;srand((unsigned)time( NULL));for(i=0; i < len; i++){for(j = 0; j < len; j ++){M[i * len + j] = rand() % 50;//if (M[i * len + j] < 20 )// M[i * len + j] = 0;}}//统计矩阵中非元素的个数,占的个数达总个数的50%以上的话即可认为是稠密矩阵,因为矩阵元素是随机产生的所以只是大概估计//for(i=0; i < len*len; i++){// if(M[i]!=0)// count++;//}//printf("%d\n",count);}*/void InitMatrix(int *M,int len){//int count=0;srand((unsigned)time( NULL));for(i=0; i < len*len; i++){M[i] = rand() % 2;}//统计矩阵中非0元素的个数,占的个数达总个数的50%以上的话即可认为是稠密矩阵,因为矩阵元素是随机产生的所以只是大概估计//for(i=0; i < len*len; i++){// if(M[i]!=0)// count++;//}//printf("%d\n",count);}int main(int argc,char *argv[]){MPI_Status status;MPI_Init(&argc,&argv);MPI_Comm_rank(MPI_COMM_WORLD,&procsID);//获得当前进程号MPI_Comm_size(MPI_COMM_WORLD,&procsNum);//获得进程个数line = Length/procsNum;//将数据分为(进程数)个块,主进程也要处理数据A = (int*)malloc(sizeof(int)*Length*Length);B = (int*)malloc(sizeof(int)*Length*Length);C = (int*)malloc(sizeof(int)*Length*Length);//缓存大小大于等于要处理的数据大小,大于时只需关注实际数据那部分buffer = (int*)malloc(sizeof(int)*Length*line);//数据分组大小ans = (int*)malloc(sizeof(int)*Length*line);//保存数据块结算的结果//主进程对矩阵赋初值,并将矩阵B广播到各进程,将矩阵A分组广播到各进程if (procsID==0){//矩阵赋初值InitMatrix(A,Length);//Sleep(1000);//停顿1s,使得矩阵A和B产生的随机元素不一样(但是在命令窗口不识别它的头文件windows.h)InitMatrix(B,Length);startTime = MPI_Wtime();//将矩阵B发送给其他从进程for (i=1;i<procsNum;i++){MPI_Send(B,Length*Length,MPI_INT,i,0,MPI_COMM_WORLD);}//依次将A的各行发送给各从进程for (i=1;i<procsNum;i++){MPI_Send(A+(i-1)*line*Length,Length*line,MPI_INT,i,1,MPI_COMM_WORLD);}//接收从进程计算的结果for (k=1;k<procsNum;k++){MPI_Recv(ans,line*Length,MPI_INT,k,3,MPI_COMM_WORLD,&status);//将结果传递给数组Cfor (i=0;i<line;i++){for (j=0;j<Length;j++){C[((k-1)*line+i)*Length+j]=ans[i*Length+j];}}}//计算A剩下的数据for (i=(procsNum-1)*line;i<Length;i++){for (j=0;j<Length;j++){temp=0;for (k=0;k<Length;k++)temp += A[i*Length+k]*B[k*Length+j];C[i*Length+j]=temp;}}endTime = MPI_Wtime();totalTime=endTime-startTime;printf("并行稠密矩阵乘法过程总共花的时间:%.4fs\n",totalTime);}//其他进程接收数据,计算结果后,发送给主进程else{//接收广播的数据(矩阵N)MPI_Recv(B,Length*Length,MPI_INT,0,0,MPI_COMM_WORLD,&status);MPI_Recv(buffer,Length*line,MPI_INT,0,1,MPI_COMM_WORLD,&status);//计算乘积结果,并将结果发送给主进程for (i=0;i<line;i++){for (j=0;j<Length;j++){temp=0;for(k=0;k<Length;k++)temp += buffer[i*Length+k]*B[k*Length+j];ans[i*Length+j]=temp;}}//将计算结果传送给主进程MPI_Send(ans,line*Length,MPI_INT,0,3,MPI_COMM_WORLD);}MPI_Finalize();//结束return 0;}DenseMulMatrixSerial.c#include <stdio.h>#include <stdlib.h>#include <time.h>//#include <windows.h>#define Length 1000int *A,*B,*C;//A、B、C一维数组分别记录矩阵A、B、C,以行优先的方式存储int i,j,k;clock_t startTime, endTime;double totalTime;//初始化矩阵/*void InitMatrix(int *M,int len){//产生0到49之间的随机数//int count=0;srand((unsigned)time( NULL));for(i=0; i < len; i++){for(j = 0; j < len; j ++){M[i * len + j] = rand() % 50;//if (M[i * len + j] < 20 )// M[i * len + j] = 0;}}//统计矩阵中非元素的个数,占的个数达总个数的50%以上的话即可认为是稠密矩阵,因为矩阵元素是随机产生的所以只是大概估计//for(i=0; i < len*len; i++){// if(M[i]!=0)// count++;//}//printf("%d\n",count);}*/void InitMatrix(int *M,int len){//int count=0;srand((unsigned)time( NULL));for(i=0; i < len*len; i++){M[i] = rand() % 2;}//统计矩阵中非0元素的个数,占的个数达总个数的50%以上的话即可认为是稠密矩阵,因为矩阵元素是随机产生的所以只是大概估计//for(i=0; i < len*len; i++){// if(M[i]!=0)// count++;//}//printf("%d\n",count);}int main(){//矩阵A乘以矩阵B,结果为矩阵C,A、B、C均用一维的数组存储,有Length*Length个单元//动态为矩阵分配空间A = (int *)malloc(sizeof(int)*Length*Length);B = (int *)malloc(sizeof(int)*Length*Length);C = (int *)malloc(sizeof(int)*Length*Length);//初始化矩阵A BInitMatrix(A,Length);//Sleep(1000);//停顿1s,使得矩阵A和B中随机产生的元素不一样InitMatrix(B,Length);startTime = clock();//矩阵乘法过程for(i = 0; i < Length; i ++){for(j = 0; j < Length; j ++){C[i * Length + j] = 0;for (k = 0; k < Length; ++k){C[i * Length + j] += A[i * Length + k] * B[k * Length + j];}}}endTime = clock();//串行矩阵乘法总共用的时间totalTime = (double)(endTime - startTime) / CLOCKS_PER_SEC;printf("串行稠密矩阵乘法过程总共花的时间:%.4fs\n",totalTime);return 0;}SparseMulMatrixMPI.c#include <stdio.h>#include <stdlib.h>#include <mpi.h>#include <time.h>//#include <windows.h>#define Length 1000int *A,*B,*C;//A、B、C一维数组分别记录矩阵A、B、C,以行优先的方式存储int *buffer,*ans;int temp;//临时变量,存储乘法过程中的中间值double startTime,endTime,totalTime;//startTime endTime totalTime分别表示矩阵乘之前的时间、之后的时间,以及矩阵乘所花费的时间int procsID,procsNum;//进程标识、进程个数int i,j,k;int m,n;//统计矩阵中1时用int line;//每个进程可以分配的矩阵行数//初始化矩阵/*void InitMatrix(int *M,int len){//产生0 48 49 三个数//int count=0;srand((unsigned)time( NULL));for(i=0; i < len; i++){for(j = 0; j < len; j ++){M[i * len + j] = rand() % 50;if (M[i * len + j] < 48 )M[i * len + j] = 0;}}//统计矩阵中0元素的个数,占的个数小于总个数的5%的话即为稀疏矩阵,因为矩阵元素是随机产生的所以只是大概估计//for(i=0; i < len*len; i++){// if(M[i]==0)// count++;//}//printf("%d\n",count);}*/void InitMatrix(int *M,int len){//根据稀疏矩阵非0元素少于总元素个数的5%的原则设置下面的程序,随机产生元素位置,令其位置上的元素为1,其余为0//int count=0;for(i=0;i<len*len;i++)M[i]=0;srand((unsigned)time( NULL));for(m=0;m<224;m++){for(n=0;n<224;n++){i=rand()%1000;j=rand()%1000;M[i*len+j]=1;}}//统计矩阵中0元素的个数,占的个数小于总个数的5%的话即为稀疏矩阵,因为矩阵元素是随机产生的所以只是大概估计//for(i=0; i < len*len; i++){// if(M[i]==0)// count++;//}//printf("%d\n",count);}int main(int argc,char *argv[]){MPI_Status status;MPI_Init(&argc,&argv);MPI_Comm_rank(MPI_COMM_WORLD,&procsID);//获得当前进程号MPI_Comm_size(MPI_COMM_WORLD,&procsNum);//获得进程个数line = Length/procsNum;//将数据分为(进程数)个块,主进程也要处理数据A = (int*)malloc(sizeof(int)*Length*Length);B = (int*)malloc(sizeof(int)*Length*Length);C = (int*)malloc(sizeof(int)*Length*Length);//缓存大小大于等于要处理的数据大小,大于时只需关注实际数据那部分buffer = (int*)malloc(sizeof(int)*Length*line);//数据分组大小ans = (int*)malloc(sizeof(int)*Length*line);//保存数据块结算的结果//主进程对矩阵赋初值,并将矩阵B广播到各进程,将矩阵A分组广播到各进程if (procsID==0){//矩阵赋初值InitMatrix(A,Length);//Sleep(1000);//停顿1s,使得矩阵A和B产生的随机元素不一样(但是在命令窗口不识别它的头文件windows.h)InitMatrix(B,Length);startTime = MPI_Wtime();//将矩阵B发送给其他从进程for (i=1;i<procsNum;i++){MPI_Send(B,Length*Length,MPI_INT,i,0,MPI_COMM_WORLD);}//依次将A的各行发送给各从进程for (i=1;i<procsNum;i++){MPI_Send(A+(i-1)*line*Length,Length*line,MPI_INT,i,1,MPI_COMM_WORLD);}//接收从进程计算的结果for (k=1;k<procsNum;k++){MPI_Recv(ans,line*Length,MPI_INT,k,3,MPI_COMM_WORLD,&status);//将结果传递给数组Cfor (i=0;i<line;i++){for (j=0;j<Length;j++){C[((k-1)*line+i)*Length+j]=ans[i*Length+j];}}}//计算A剩下的数据for (i=(procsNum-1)*line;i<Length;i++){for (j=0;j<Length;j++){temp=0;for (k=0;k<Length;k++)temp += A[i*Length+k]*B[k*Length+j];C[i*Length+j]=temp;}}endTime = MPI_Wtime();totalTime=endTime-startTime;printf("并行稀疏矩阵乘法过程总共花的时间:%.4fs\n",totalTime);}//其他进程接收数据,计算结果后,发送给主进程else{//接收广播的数据(矩阵N)MPI_Recv(B,Length*Length,MPI_INT,0,0,MPI_COMM_WORLD,&status);MPI_Recv(buffer,Length*line,MPI_INT,0,1,MPI_COMM_WORLD,&status);//计算乘积结果,并将结果发送给主进程for (i=0;i<line;i++){for (j=0;j<Length;j++){temp=0;for(k=0;k<Length;k++)temp += buffer[i*Length+k]*B[k*Length+j];ans[i*Length+j]=temp;}}//将计算结果传送给主进程MPI_Send(ans,line*Length,MPI_INT,0,3,MPI_COMM_WORLD);}MPI_Finalize();//结束return 0;}SparseMulMatrixSerial.c#include <stdio.h>#include <stdlib.h>#include <time.h>//#include <windows.h>#define Length 1000int *A,*B,*C;//A、B、C一维数组分别记录矩阵A、B、C,以行优先的方式存储int i,j,k;int m,n;//统计矩阵中1时用clock_t startTime, endTime;double totalTime;//初始化矩阵/*void InitMatrix(int *M,int len){//产生0 48 49 三个数//int count=0;srand((unsigned)time( NULL));for(i=0; i < len; i++){for(j = 0; j < len; j ++){M[i * len + j] = rand() % 50;if (M[i * len + j] < 48 )M[i * len + j] = 0;}}//统计矩阵中0元素的个数,占的个数小于总个数的5%的话即为稀疏矩阵,因为矩阵元素是随机产生的所以只是大概估计//for(i=0; i < len*len; i++){// if(M[i]==0)// count++;//}//printf("%d\n",count);}*/void InitMatrix(int *M,int len){//根据稀疏矩阵非0元素少于总元素个数的5%的原则设置下面的程序,随机产生元素位置,令其位置上的元素为1,其余为0//int count=0;for(i=0;i<len*len;i++)M[i]=0;srand((unsigned)time( NULL));for(m=0;m<224;m++){for(n=0;n<224;n++){i=rand()%1000;j=rand()%1000;M[i*len+j]=1;}}//统计矩阵中0元素的个数,占的个数小于总个数的5%的话即为稀疏矩阵,因为矩阵元素是随机产生的所以只是大概估计//for(i=0; i < len*len; i++){// if(M[i]==0)// count++;//}//printf("%d\n",count);}int main(){//矩阵A乘以矩阵B,结果为矩阵C,A、B、C均用一维的数组存储,有Length*Length个单元//动态为矩阵分配空间A = (int *)malloc(sizeof(int)*Length*Length);B = (int *)malloc(sizeof(int)*Length*Length);C = (int *)malloc(sizeof(int)*Length*Length);//初始化矩阵A BInitMatrix(A,Length);//Sleep(1000);//停顿1s,使得矩阵A和B中随机产生的元素不一样InitMatrix(B,Length);startTime = clock();//矩阵乘法过程for(i = 0; i < Length; i ++){for(j = 0; j < Length; j ++){C[i * Length + j] = 0;for (k = 0; k < Length; ++k){C[i * Length + j] += A[i * Length + k] * B[k * Length + j];}}}endTime = clock();//串行矩阵乘法总共用的时间totalTime = (double)(endTime - startTime) / CLOCKS_PER_SEC;printf("串行稀疏矩阵乘法过程总共花的时间:%.4fs\n",totalTime);return 0;}附:另一种矩阵初始化的办法//稠密矩阵的生成方法void InitMatrix(int *M,int *N,int len){srand((unsigned)time( NULL));for(i=0; i < len*len; i++){M[i] = rand() % 2;}for(i=0;i<len;i++){for(j=0;j<len;j++){N[i*len+j]=M[j*len+i];}}}//稀疏矩阵的生成方法void InitMatrix(int *M, int *N, int len){for(i=0;i<len*len;i++)M[i]=0;srand((unsigned)time( NULL));for(m=0;m<224;m++){for(n=0;n<224;n++){i=rand()%len;j=rand()%len;M[i*len+j]=1;}}for(i=0;i<len;i++){for(j=0;j<len;j++){N[i*len+j]=M[j*len+i];}}}。

并行计算实验报告(高性能计算与网格技术)

并行计算实验报告(高性能计算与网格技术)

并行计算实验报告(高性能计算与网格技术)高性能计算和网格技术实验报告实验题目OpenMP和MPI编程姓名学号专业计算机系统结构指导教师助教所在学院计算机科学与工程学院论文提交日期一、实验目的本实验的目的是通过练习掌握OpenMP 和MPI 并行编程的知识和技巧。

1、熟悉OpenMP 和MPI 编程环境和工具的使用;2、掌握并行程序编写的基本步骤;3、了解并行程序调试和调优的技巧。

二、实验要求1、独立完成实验内容;2、了解并行算法的设计基础;3、熟悉OpenMP和MPI的编程环境以及运行环境;4、理解不同线程数,进程数对于加速比的影响。

三、实验内容3.1、矩阵LU分解算法的设计:参考文档sy6.doc所使用的并行算法:在LU分解的过程中,主要的计算是利用主行i对其余各行j,(j>i)作初等行变换,各行计算之间没有数据相关关系,因此可以对矩阵A 按行划分来实现并行计算。

考虑到在计算过程中处理器之间的负载均衡,对A采用行交叉划分:设处理器个数为p,矩阵A的阶数为n,??p=,对矩阵A行交叉划分后,编号为i(i=0,1,…,p-1)的处理器存有m/nA的第i, i+p,…, i+(m-1)p行。

然后依次以第0,1,…,n-1行作为主行,将其广播给所有处理器,各处理器利用主行对其部分行向量做行变换,这实际上是各处理器轮流选出主行并广播。

若以编号为my_rank 的处理器的第i行元素作为主行,并将它广播给所有处理器,则编号大于等于my_rank的处理器利用主行元素对其第i+1,…,m-1行数据做行变换,其它处理器利用主行元素对其第i,…,m-1行数据做行变换。

根据上述算法原理用代码表示如下(关键代码):for(k = 0;k<n;k++)< p="">{for (i = 0; i < THREADS_NUM; i++) {thread_data_arrray[i].thread_id = i;thread_data_arrray[i].K_number = k;thread_data_arrray[i].chushu = a[k][k];//创建线程rc = pthread_create(&pid[i], NULL, work,(void*)&thread_data_arrray[i]);…}for (i = 0; i < THREADS_NUM; i++){//等待线程同步rc = pthread_join(pid[i], &ret); …}}void *work(void *arg){struct thread_data *my_data;my_data = (struct thread_data*)arg;int myid = my_data->thread_id; //线程IDint myk = my_data->K_number; //外层循环计数Kfloat mychushu = my_data->chushu; //对角线的值int s, e;int i, j;s = (N-myk-1) * myid / THREADS_NUM; //确定起始循环的行数的相对位置e = (N-myk-1) * (myid + 1) / THREADS_NUM;//确定终止循环的行数的相对位置for (i = s+myk+1; i < e+myk+1; i++) //由于矩阵规模在缩小,找到偏移位置 { a[i][myk]=a[i][myk]/mychushu; for (j = myk+1; j < N; j++) a[i][j]=a[i][j]-a[i][myk]*a[myk][j]; }//printMatrix(a); return NULL;}第一部分为入口函数,其创建指定的线程数,并根据不同的线程id 按行划分矩阵,将矩阵的不同部分作为参数传递给线程,在多处理器电脑上,不同的线程并行执行,实现并行计算LU 分解。

并行计算实验报告

并行计算实验报告

分析 :这样的加速比 , 是符合预测 , 很好的 . 附 :(实验 源码 ) 1 pi.cpp #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <ctime> #include <cassert>
#include <climits> #include <iostream> #include <iomanip> #include <string> #include <vector> #include <set> #include <map> #include <queue> #include <deque> #include <bitset> #include <algorithm> #include <omp.h> #define MST(a, b) memset(a, b, sizeof(a)) #define REP(i, a) for (int i = 0; i < int(a); i++) #define REPP(i, a, b) for (int i = int(a); i <= int(b); i++) #define NUM_THREADS 4 using namespace std; const int N = 1e6; double sum[N]; int main() { ios :: sync_with_stdio(0); clock_t st, ed; double pi = 0, x; //串行 st = clock(); double step = 1.0 / N; REP(i, N) { x = (i + 0.5) * step; pi += 4.0 / (1.0 + x * x); } pi /= N; ed = clock(); cout << fixed << setprecision(10) << "Pi: " << pi << endl; cout << fixed << setprecision(10) << "串行用时: " << 1.0 * (ed - st) / CLOCKS_PER_SEC << endl; //并行域并行化 pi = 0; omp_set_num_threads(NUM_THREADS); st = clock(); int i; #pragma omp parallel private(i) { double x; int id; id = omp_get_thread_num();

OpenMP矩阵相乘

OpenMP矩阵相乘

多核软件设计实验指导――OpenMP矩阵相乘开发者:开发时间:版本号:一. 问题描述矩阵相乘是线性代数中最常见的问题之一,它在数值计算中有广泛的应用,在计算机的世界里,矩阵相乘扮演着一个不可或缺的角色。

设A 和B 是2个 n n ⨯ 矩阵,,它们的乘积AB 同样是一个n n ⨯矩阵。

A 和B 乘积矩阵C 中元素C ]][[]][[1]][[j k B k i A nk j i ∑==二、串行算法描述若以上面的定义来计算A 和B 的乘积矩阵C ,则每计算C 的一个元素]][[j i C ,需要作n 次乘法运算和n -1次加法运算。

因此,算出矩阵C 的2n 个元素所需的计算时间为)(3n O 。

从程序运行的效率上来分析,如果n 比较大的时候,会耗费大量的空间和时间。

20世纪60年代末期,Strassen 采用了类似在大整数乘法中用过的分治技术,将计算2个n 阶矩阵乘积所需的计算时间改进到)()(81.27log n n O =O ,其基本思想还是使用分治法。

显然,这也没能够大幅度地提高运行速度和效率。

将矩阵a 与矩阵b 相乘得到矩阵c 的代码如下:for(i=0;i<dim;i++){ for(j=0;j<dim;j++){ c(i,j)=0;for(k=0;k<dim;k++){c(i ,j)+=a(i ,k)*b(k,j);}}}三、并行算法下面使用了OpenMP ,修改后的矩阵相乘程序使最外面的迭代在多个线程间静态分割,如图(a )所示:#pragma omp paralllel default(private) shared(a,b,c,dim) num_threads(2) #pragma omp for schedule(static)for(i=0;i<dim;i++){ for(j=0;j<dim;j++){ c(i,j)=0;for(k=0;k<dim;k++){c(i ,j)+=a(i ,k)*b(k,j);}}}Static调度类的一般形式为schedule(static[,chunk-size])。

矩阵乘法MPI并行程序报告

矩阵乘法MPI并行程序报告

1. 实验目的1.1掌握集群的使用方法。

1.2掌握以并行的方式分析问题、设计并行程序的方法。

1.3掌握如何对并行程序进行简单的性能分析2. 实验要求2.1使用MPI、OpenMp等并行程序设计方法设计矩阵乘法的并行程序。

2.2随机产生所需的矩阵元素,数据项不得少于1000*1000。

2.3尽量设计较高的加速比3. 实验环境3.1硬件环境:两个集群节点blade13、blade15。

3.2软件环境:Linux、gcc、Win7、VC++6.0。

3.3连接方式:Xmanager Enterprise4.0远程桌面连接211.69.198.203。

4. 实验程序4.1随机算法产生矩阵:srand((unsigned int)time(NULL));for (i=0; i<N; i++){for (j=0; j<N; j++){A[i][j] = rand() % 10;B[i][j] = rand() % 10;C[i][k] = 0;}}4.2串行程序设计time(&start);for (i=0; i<M; i++){for (k=0; k<M; k++){C[i][k] = 0;for (j=0; j<M; j++){C[i][k] += A[i][j]*B[j][k];}}}4.3并行程序设计MPI_Init(&argc,&argv) 和MPI_Finalize() MPI_Init用来初始化MPI执行环境,建立多个MPI 进程之间的联系,为后续通信做准备。

而MPI_Finalize则是结束MPI执行环境。

这两个函数就是定义MPI程序的并行区的,除了检测是否初始化的函数之外,不应该在这两个函数定义的区域外调用其它MPI函数。

这两个函数都返回整型值,标识函数是否调用成功。

intMPI_Comm_rank(MPI_Comm comm, int *rank) MPI_Comm_rank函数用来标识各个MPI进程,获取调用该函数进程的进程号,将自身与其他进程区分。

矩阵乘法实验报告总结

矩阵乘法实验报告总结

矩阵乘法是线性代数中一个基础且重要的运算,广泛应用于科学计算、数据分析和工程领域。

为了深入了解矩阵乘法的并行化实现,提高计算效率,本实验旨在通过MPI(Message Passing Interface)并行编程技术,实现矩阵乘法的并行计算,并分析其性能。

二、实验内容与方法1. 实验环境操作系统:Ubuntu Linux编译器:gcc并行计算平台:632核CPU、400GB内存的分布内存并行计算平台2. 实验方法(1)矩阵乘法算法本实验采用经典的矩阵乘法算法,即按行优先顺序进行计算。

具体步骤如下:① 将矩阵A、B、C划分为p个块,每个块包含m/p行和n/p列。

② 每个进程负责计算C的一个子块,即计算A的m/p行与B的n/p列的乘积。

③ 进程间通过MPI通信进行数据交换,实现并行计算。

(2)MPI编程本实验采用MPI编程实现矩阵乘法。

主要使用以下MPI语句:① MPI_Init:初始化MPI环境。

② MPI_Comm_size:获取进程总数。

③ MPI_Comm_rank:获取进程编号。

④ MPI_Send:发送数据。

⑤ MPI_Recv:接收数据。

⑥ MPI_Finalize:结束MPI环境。

1. 矩阵乘法结果验证通过比较串行计算和并行计算的结果,验证了程序的正确性。

2. 性能分析(1)执行时间在固定矩阵规模n=1000的情况下,分别测试进程数取1、2、4、8、16、32、64时的执行时间。

结果表明,随着进程数的增加,执行时间逐渐减少,且呈近似线性关系。

(2)加速比加速比是指并行计算时间与串行计算时间的比值。

本实验计算了不同进程数下的加速比,发现随着进程数的增加,加速比逐渐提高,且在进程数达到一定数量后,加速比趋于稳定。

(3)并行效率并行效率是指实际加速比与理论加速比之比。

本实验计算了不同进程数下的并行效率,发现随着进程数的增加,并行效率逐渐提高,但存在一个峰值,之后逐渐降低。

四、实验结论与展望1. 结论本实验通过MPI并行编程技术实现了矩阵乘法的并行计算,验证了程序的正确性。

OpenMP实现矩阵乘法以及转置算法对效率的影响

OpenMP实现矩阵乘法以及转置算法对效率的影响

OpenMp实现矩阵乘法与相关内容分析姓名:XXX学号:XXXXXXXXXX日期:2015年6月1.概述1.1实验内容:1)用OpenMP实现最基本的数值算法“矩阵乘法”2)掌握for编译指导语句3)对比不同进程数对并行效率的影响4)对比不同阶数对并行效率的影响5)对比不同阶矩阵转置前后效率提升的影响1.2 实验环境:1)硬件环境:CPU为20核心40线程、32G内存计算机2)软件环境:Linux、G++、OpenMPI3)编程语言:C++1.3 程序描述:用OpenMP编写两个n阶方阵a和b相乘的程序,a和b中的所有值均为1~100的随机数,n可在input文件中规定,结果存放在方阵c中,其中乘法用for编译指导语句实现并行化操作输入:input文件,其中为方阵的阶数n、并行域的进程数输出:每个子函数的执行时间、方阵a、b、c中的值程序的源代码如下:其中的子函数分别是:串行计算,转置后的串行计算,OpenMP并行计算,转置后的OpenMP 并行计算,打印三个矩阵。

#include<iostream>#include<stdlib.h>#include<sys/time.h>#include<omp.h>#include<math.h>#include<fstream>using namespace std;#define MAX 2000int a[MAX][MAX], b[MAX][MAX];int c[MAX][MAX];//计时器class timer{struct timeval start,end;double time_use;public:void clock_on(){gettimeofday(&start,NULL); //Get the time of starting}void clock_end(){gettimeofday(&end,NULL); //Get the time of ending}void time(){time_use=(__sec)*1000+ (__usec)/1000; //Get the time(ms) cout<<"totally use:"<<time_use/1000<<"s"<<endl;}};//串行计算矩阵乘法void Serial(int n){int i, j, k;for(i=0;i<n;i++) //Initialize the matrix c{for(j=0;j<n;j++){c[i][j]=0;}}for(i = 0;i<n;i++){for(j=0;j<n;j++){for(k=0;k<n;k++){c[i][j]=c[i][j]+a[i][k]*b[k][j];}}}}//串行计算转置后的矩阵乘法void Serial_Transposition(int n){int i, j, k;for(i=0;i<n;i++) //Initialize the matrix c{for(j=0;j<n;j++){c[i][j]=0;}}for(j=0;j<n;j++){for(k=0;k<n;k++){r[k]=b[k][j];}for(i=0;i<n;i++){for(k=0;k<n;k++){c[i][j]=c[i][j]+a[i][k]*r[k];}}}}//并行计算矩阵乘法void Parallel_OMP(int n, int num_thread){int i, j, k;omp_set_num_threads(num_thread);for(i=0;i<n;i++) //Initialize the matrix c{for(j=0;j<n;j++){c[i][j]=0;}}#pragma omp parallel shared(a,b,c) private(i,j,k){#pragma omp for schedule(dynamic) //Types of scheduling:static,dynamic,guided for(i=0;i<n;i++){for(j=0;j<n;j++){for(k=0;k<n;k++){c[i][j]=c[i][j]+a[i][k]*b[k][j];}}}}}//并行计算转置后的矩阵乘法void Parallel_OMP_Transposition(int n, int num_thread){int i, j, k;int r[n];omp_set_num_threads(num_thread);for(i=0;i<n;i++) //Initialize the matrix c{for(j=0;j<n;j++){c[i][j]=0;}#pragma omp parallel shared(a,b,c) private(i,j,k){#pragma omp for schedule(dynamic) //Types of scheduling:static,dynamic,guided for(j=0;j<n;j++){for(k=0;k<n;k++){r[k]=b[k][j];}for(i=0;i<n;i++){for(k=0;k<n;k++){c[i][j]=c[i][j]+a[i][k]*r[k];}}}}}//打印三个矩阵void print(int n){int i,j;for(i=0;i<n;i++){printf("\n");for(j=0;j<n;j++){printf("%10d ",a[i][j]);}}printf("\n");for(i=0;i<n;i++){printf("\n");for(j=0;j<n;j++){printf("%10d ",b[i][j]);}}printf("\n");for(i=0;i<n;i++){printf("\n");for(j=0;j<n;j++){printf("%10d ",c[i][j]);}}printf("\n");}//主程序int main(){int n, num_thread;int i,j;timer clock;FILE *fp;fp=fopen("input","r");if(fp==NULL)return -1;while(!feof(fp)){fscanf(fp,"%d%d",&n,&num_thread);}fclose(fp);for(i=0;i<n;i++) //Give matrix a and b some random values between 1 and 100.{for(j=0;j<n;j++){a[i][j]= rand()%100+1;b[i][j]= rand()%100+1;}}printf("\nSerial:\n\n");clock.clock_on();Serial(n);clock.clock_end();clock.time();print(n);printf("\nSerial_Transposition:\n\n");clock.clock_on();Serial_Transposition(n);clock.clock_end();clock.time();print(n);printf("\nParallel_OMP:\n\n");clock.clock_on();Parallel_OMP(n,num_thread);clock.clock_end();clock.time();print(n);printf("\nParallel_OMP_Transposition:\n\n");clock.clock_on();Parallel_OMP_Transposition(n,num_thread);clock.clock_end();clock.time();print(n);return 0;}1.4 对转置算法的说明由于矩阵的数据存储为按行存储,在直接做矩阵乘法时,需要不停地读取b中每一列的数据,而这些数据没有连续存储,这样会使得读取数据的时间增大。

基于openmp的并行矩阵乘法

基于openmp的并行矩阵乘法

基于OpenMP的并行矩阵乘法1. 概述并行计算是当代计算机科学领域中的一个重要研究方向,随着多核和并行处理器的广泛应用,利用并行计算技术提高计算效率成为了迫切的需求。

矩阵乘法作为线性代数中的重要运算,在科学计算、图形学和机器学习等领域有着广泛的应用。

基于OpenMP的并行矩阵乘法算法能够充分利用多核处理器的并行计算能力,提高计算效率。

2. OpenMP并行编程简介OpenMP是一种基于共享内存的并行编程技术,可以在C/C++、Fortran等编程语言中使用。

它通过在源代码中嵌入一些指令来实现并行化,使得程序员可以很方便地对现有代码进行并行化改造。

OpenMP提供了一系列的指令和库函数,使得并行程序的编写变得更加容易。

3. 矩阵乘法的串行算法矩阵乘法的串行算法是最常见的,其时间复杂度为O(n^3)。

对于两个矩阵A和B相乘,其乘积矩阵C的元素C[i][j]计算方式为:C[i][j] = ΣA[i][k]*B[k][j],其中k取值范围为1到矩阵的行数或列数。

串行算法的实现比较简单,但在大规模矩阵计算时效率较低。

4. 基于OpenMP的并行矩阵乘法算法基于OpenMP的并行矩阵乘法算法可以利用多核处理器的并行计算能力,提高计算效率。

下面我们将介绍一种基于OpenMP的并行矩阵乘法算法的实现方法。

5. 并行矩阵乘法的实现在使用OpenMP进行并行化时,可以针对矩阵乘法中的循环结构进行并行化处理。

以矩阵乘法C=AB为例,其中A为m×n矩阵,B为n×p矩阵,C为m×p矩阵。

我们可以将矩阵乘法按照不同的方法进行并行化,并结合OpenMP的指令进行并行计算。

一种常见的方法是使用循环并行化,将内层的乘法运算循环并行化,即将矩阵C的计算过程并行化。

另一种方法是使用数据并行化,将矩阵A、B、C的元素分配给不同的线程进行计算,然后将结果合并得到最终结果。

6. 并行矩阵乘法算法的优化在实际应用中,我们可以针对具体的矩阵大小和计算资源进行优化。

mpi openmp 案例

mpi openmp 案例

mpi openmp 案例MPI和OpenMP是并行计算中常用的编程模型,它们可以在多核和分布式系统中实现并行计算,提高计算效率。

本文将介绍一些MPI和OpenMP的案例,以展示它们在实际应用中的优势和用法。

引言概述:MPI和OpenMP是并行计算中常用的编程模型,它们分别适用于分布式和共享内存系统。

MPI(Message Passing Interface)是一种消息传递的并行编程模型,适用于分布式系统中的并行计算;而OpenMP是一种共享内存的并行编程模型,适用于多核系统中的并行计算。

下面将分别介绍它们在实际应用中的案例。

正文内容:1. MPI案例1.1 分布式矩阵乘法- 使用MPI实现矩阵乘法可以将计算任务分配给不同的进程,每个进程负责计算一部分矩阵乘法的结果。

- 使用MPI的消息传递机制,进程之间可以相互通信,将计算结果进行汇总,得到最终的矩阵乘法结果。

- 这种分布式矩阵乘法可以充分利用分布式系统的计算资源,提高计算效率。

1.2 并行排序算法- 使用MPI可以将排序任务分配给不同的进程,每个进程负责排序一部分数据。

- 进程之间可以通过消息传递机制交换数据,实现分布式的排序算法。

- 这种并行排序算法可以大大减少排序的时间复杂度,提高排序的效率。

2. OpenMP案例2.1 并行矩阵运算- 使用OpenMP可以将矩阵运算任务分配给不同的线程,每个线程负责计算一部分矩阵运算的结果。

- 多个线程可以共享内存,可以直接访问共享的数据,减少了数据的拷贝和通信开销。

- 这种并行矩阵运算可以充分利用多核系统的计算资源,提高计算效率。

2.2 并行图像处理- 使用OpenMP可以将图像处理任务分配给不同的线程,每个线程负责处理一部分图像数据。

- 多个线程可以并行地对图像进行处理,提高了图像处理的速度。

- 这种并行图像处理可以广泛应用于图像处理领域,如图像滤波、图像分割等。

总结:MPI和OpenMP是并行计算中常用的编程模型,它们分别适用于分布式和共享内存系统。

OpenMP并行实验报告

OpenMP并行实验报告

并行实验报告一、积分计算圆周率积分计算圆周率的向量优化串行版本的设计任务:理解积分求圆周率的方法,将其用C代码实现。

注意:理论上,dx越小,求得的圆周率越准确;在计算机中由于表示的数据是有精度范围的,如果dx太小,积分次数过多,误差积累导致结果不准确。

以下为串行代码:#include<>#include<>#define Ndouble get_pi(int dt){double pi=;double delta =dt;int i;for(i=0; i<dt; i++){double x=(double)i/dt;pi+=delta/+x*x);}return pi*4;}int main(){int dx;double pai;double start,finish;dx=N;start=clock();pai=get_pi(dx);finish=clock();printf("%.8lf\n",pai);printf("%.8lfS\n",(double)(finish-start)/CLOCKS_PER_SEC); return 0;}时间运行如下:第一次:time=第二次:time=第三次:time=三次平均为:SSE向量优化版本设计任务:此部分需要给出单精度和双精度两个优化版本。

注意:(1)测试均在划分度为10的7次方下完成。

以下是SSE双精度的代码:#include<>#include<>#include<>#define Ndouble get_pi(int dt){double pi=;double delta =dt;int i;for(i=0; i<dt; i++){double x=(double)i/dt;pi+=delta/+x*x);}return pi*4;}double get_pi_sse(size_t dt){double pi=;double delta =dt;__m128d xmm0,xmm1,xmm2,xmm3,xmm4;xmm0=_mm_set1_pd;xmm1=_mm_set1_pd(delta);xmm2=_mm_set_pd(delta,;xmm4=_mm_setzero_pd();for(long int i=0; i<=dt-2; i+=2){xmm3= _mm_set1_pd((double)i*delta);xmm3= _mm_add_pd(xmm3,xmm2);xmm3= _mm_mul_pd(xmm3,xmm3);xmm3= _mm_add_pd(xmm0,xmm3);xmm3= _mm_div_pd(xmm1,xmm3);xmm4= _mm_add_pd(xmm4,xmm3);}double tmp[2] __attribute__((aligned(16)));_mm_store_pd(tmp,xmm4);pi+=tmp[0]+tmp[1]/*+tmp[2]+tmp[3]*/;return pi*;}int main(){int dx;double pai;double start,finish;dx=N;start=clock();pai=get_pi_sse(dx);finish=clock();printf("%.8lf\n",pai);printf("%.8lfS\n",(double)((finish-start)/CLOCKS_PER_SEC)); return 0;}时间运行如下:第一次:time=第二次:time=第三次:time=三次平均为:以下是SSE单精度的代码:#include<>#include<>#include<>#define Nfloat get_pi_sse(size_t dt){float pi=;float delta =dt;__m128 xmm0,xmm1,xmm2,xmm3,xmm4; xmm0=_mm_set1_ps;xmm1=_mm_set1_ps(delta);xmm2=_mm_set_ps(delta*3,delta*2,delta,; xmm4=_mm_setzero_ps();for(long int i=0; i<=dt-4; i+=4){xmm3= _mm_set1_ps((float)i*delta);xmm3= _mm_add_ps(xmm3,xmm2);xmm3= _mm_mul_ps(xmm3,xmm3);xmm3= _mm_add_ps(xmm0,xmm3);xmm3= _mm_div_ps(xmm1,xmm3);xmm4= _mm_add_ps(xmm4,xmm3);}float tmp[4] __attribute__((aligned(16))); _mm_store_ps(tmp,xmm4);pi+=tmp[0]+tmp[1]+tmp[2]+tmp[3];return pi*;}int main(){int dx;float pai;double start,finish;dx=N;start=clock();pai=get_pi_sse(dx);finish=clock();printf("%.8f\n",pai);printf("%.8lfS\n",(double)((finish-start)/CLOCKS_PER_SEC));return 0;}时间运行如下:第一次:time=第二次:time=第三次:time=三次平均为:AVX向量优化版本设计任务:此部分需要给出单精度和双精度两个优化版本注意:(1)测试均在划分度为10的7次方下完成。

矩阵乘法的并行化实验报告

矩阵乘法的并行化实验报告

北京科技大学计算机与通信工程学院实验报告实验名称:学生姓名:专业:班级:学号:指导教师:实验成绩:________________________________实验地点:实验时间:2015年05月一、实验目的与实验要求1、实验目的1对比矩阵乘法的串行和并行算法,查看运行时间,得出相应的结论;2观察并行算法不同进程数运行结果,分析得出结论;2、实验要求1编写矩阵乘法的串行程序,多次运行得到结果汇总;2编写基于MPI,分别实现矩阵乘法的并行化。

对实现的并行程序进行正确性测试和性能测试,并对测试结果进行分析。

二、实验设备(环境)及要求《VS2013》C++语言MPICH2三、实验内容与步骤实验1,矩阵乘法的串行实验(1)实验内容编写串行程序,运行汇总结果。

(2)主要步骤按照正常的矩阵乘法计算方法,在《VS2013》上编写矩阵乘法的串行程序,编译后多次运行,得到结果汇总。

实验2矩阵乘法的并行化实验3个总进程5个总进程7个总进程9个进程16个进程四:实验结果与分析(一)矩阵乘法并行化矩阵并行化算法分析:并行策略:1间隔行带划分法算法描述:将C=A*B中的A矩阵按行划分,从进程分得其中的几行后同时进行计算,最后通信将从进程的结果合并的主进程的C矩阵中对于矩阵A*B如图:进程1:矩阵A第一行进程2:矩阵A第二行进程3:矩阵A第三行进程1:矩阵A第四行时间复杂度分析:f(n) =6+2+8+k*n+k*n+k*n+3+10+n+k*n+k*n+n+2(k为从进程分到的行数)因此O(n)=(n);空间复杂度分析:从进程的存储空间不共用,f(n)=n;因此O(n)=(n);2间隔行带划分法算法描述:将C=A*B中的A矩阵按行划分,从进程分得其中的几行后同时进行计算,最后通信将从进程的结果合并的主进程的C矩阵中对于矩阵A*B如图:进程1:矩阵A第一行进程2:矩阵A第二行进程3:矩阵A第三行进程3:矩阵A第四行时间复杂度分析:f(n) =6+2+8+k*n+k*n+k*n+3+10+n+k*n+k*n+n+2 (k为从进程分到的行数)因此O(n)=(n);空间复杂度分析:从进程的存储空间不共用,f(n)=n;因此T(n)=O(n);测试环境简介:《VS2013》Win7旗舰版正确性测试结果:并行结果:串行结果:通过比较发现两者相同,因此可以确定运算结果正确。

基于openMP的并行计算实验

基于openMP的并行计算实验

并行计算实验报告课程:并行计算姓名:郑波学号44班级:计算机科学与技术13-2班日期:2015年12月7日实验一:OpenMP基本使用一、实验目的1、熟悉OpenMP编程。

2、比较串行算法与并行算法在执行时间上的差别;3、考察线程数目使用不同对并行算法执行时间的影响;4、考察运算规模N对串、并行算法执行时间上的影响。

二、实验内容1、使用OpenMP进行两个矩阵A和B的加法,并分析串行、并行时间的差别以及问题规模对程序运行时间的影响三、实验步骤1、整个程序的设计流程①全局变量设置三个宏定义过的size×size的二维数组啊a,b,c。

②初始化a数组为全1,b数组为全2③通过omp_set_num_threads()库函数设置线程数④调用openMP库函数omp_get_wtime()获取当前时间start#pragma omp parallel for开始做并行区部分…结束后再次调用omp_get_wtime()获取时间end,end-start即为并行消耗时间⑤再次调用时间函数更新strat串行做一边矩阵相加更新end,end-start即为串行耗时代码如下:#include<iostream>#include<omp.h>#define size 10000using namespace std;int a[size][size],b[size][size],c[size][size];int main(){for(int i=0;i!=size;++i) //initial the matrixfor(int j=0;j!=size;++j){a[i][j]=1;b[i][j]=2;}double start=omp_get_wtime();omp_set_num_threads(4);#pragma omp parallel forfor(int i=0;i<size;++i)for(int j=0;j<size;++j)c[i][j]=a[i][j]+b[i][j];double end=omp_get_wtime();cout<<"并行运行时间:"<<end-start<<endl;start=omp_get_wtime();for(int i=0;i<size;++i)for(int j=0;j<size;++j)c[i][j]=a[i][j]+b[i][j];end=omp_get_wtime();cout<<"串行运行时间:"<<end-start<<endl;system("pause");}2、问题规模对串、并行程序时间的影响(A、B矩阵的大小为N*M)(1)通过不断增加问题规模,观察串行和并行程序的执行时间,得到如下表格的时间消耗数据:(2)一定程度的时候,并行运行的速度较串行有了提升。

CPU-OpenMP和GPU-CUDA并行计算技术对矩阵乘法运算的加速效果分析

CPU-OpenMP和GPU-CUDA并行计算技术对矩阵乘法运算的加速效果分析

Science &Technology Vision 科技视界0前言在信息化技术不断发展的今天,人们处在“大数据”时代。

由于数据量巨大,普通的串行计算方式计算效率低下,无法满足人们对数据进行快速处理的需求。

因此,如何能够提高计算机处理“大数据”的计算效率已成为人们日益关注的话题。

为了减少计算时间、提升计算效率,并行计算的出现成为解决上述问题的有效方法。

与普通的串行计算相比,并行计算将计算任务分配到计算机的多个处理器协同处理,从而提高计算效率。

随着并行计算结果的发展,并行算法也逐渐成熟。

目前,人们采用的并行计算技术大致可能分为两种:一是基于CPU (Central Processing Unit )多核多线程的并行计算;二是基于GPU (Graphics Processing Unit )的通用并行计算。

对于CPU 并行计算,根据并行粒度的不同可分为“共享式内存结构”和“分布式内存结构”[1]。

对于“共享式内存结构”的并行计算,OpenMP (Open Multi -Processing )作为该类型计算技术的代表,已被广泛应用于数据处理及科学计算中。

采用OpenMP 做并行计算具有编程简单、源程序改变小等优点[2]。

基于GPU 的并行计算技术是近年来发展起来的新技术。

与基于CPU 的并行计算相比,GPU 并行计算具有硬件成本低、加速效果显著的优点。

随着NVIDIA 通用计算架构CUDA (Compute Unified Device Architecture )的提出,人们用GPU 做并行计算的编程难度大为降低[3]。

本文旨在采用CPU -OpenMP 和GPU -CUDA 并行计算技术进行不同阶矩阵的乘法运算,并对比这两种并行计算技术相对于串行计算(CPU 单线程)的加速效果。

此外,我们也对GPU -CUDA 计算所产生的计算误差进行了简要分析。

1CPU-OpenMP 和GPU-CUDA 并行计算技术CPU -OpenMP 是一种API (Application Program Interface ),用于编写可移植的多线程应用程序,并且无需进行复杂的线程创建、同步、负载平衡和销毁工作。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

深圳大学
实验报告
课程名称:并行计算
实验名称:矩阵乘法的OpenMP实现及性能分析姓名:
学号:
班级:
实验日期:2011年10月21日、11月4日
一. 实验目的
1) 用OpenMP 实现最基本的数值算法“矩阵乘法” 2) 掌握for 编译制导语句 3) 对并行程序进行简单的性能
二. 实验环境
1) 硬件环境:32核CPU 、32G 存计算机;
2) 软件环境:Linux 、Win2003、GCC 、MPICH 、VS2008;
4) Windows 登录方式:通过远程桌面连接192.168.150.197,用户名和初始密码都是自己的学号。

三. 实验容
1. 用OpenMP 编写两个n 阶的方阵a 和b 的相乘程序,结果存放在方阵c 中,其中乘法用for 编译制导语句实现并行化操作,并调节for 编译制导中schedule 的参数,使得执行时间最短,写出代码。

方阵a 和b 的初始值如下:
⎥⎥⎥⎥⎥⎥⎥⎥⎦

⎢⎢⎢⎢⎢⎢⎢⎢⎣⎡-++++=12,...,2,1,..2,...,5,4,31,...,4,3,2,...,3,2,1n n n n n n n a ⎥⎥⎥⎥⎥⎥⎥⎥

⎤⎢⎢⎢⎢⎢⎢⎢⎢⎣⎡=
1,...,1,1,1..1,...,1,1,11,...,1,1,11,...,
1,1,1b 输入:
方阵的阶n 、并行域的线程数 输出:
c 中所有元素之和、程序的执行时间 提示:
a,b,c 的元素定义为int 型,c 中所有元素之各定义为long long 型。

Windows 计时:
用<time.h>中的clock_t clock( void )函数得到当前程序执行的时间 Linux 计时:
#include <sys/time.h>
timeval start,end;
gettimeofday(&start,NULL);
gettimeofday(&end,NULL);
cout<<"execution time:"<< (__sec)+(double)(__usec)/
1000000<<"seconds" <<endl;
答:
在windows下使用Microsofe Visual Studio编程,源代码如下:
#include<omp.h>
#include<stdio.h>
#include<time.h>
#define NN 2000
int a[NN][NN], b[NN][NN];
long long c[NN][NN];
void solve(int n, int num_thread)
{
int i, j, t, k, time;
clock_t startTime, endTime;
long long sum;
omp_set_num_threads(num_thread);
for(i=0;i<n;i++)//对矩阵a和矩阵b进行初始化
{
t=i+1;
for(j=0;j<n;j++)
{
a[i][j]=t++;
b[i][j]=1;
}
}
startTime=clock();
sum=0;
#pragma omp parallel shared(a,b,c) private(i,j,k)
{
#pragma omp for schedule(dynamic)
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
c[i][j]=0;
for(k=0;k<n;k++)
{
c[i][j]+=a[i][k]*b[k][j];
}
}
}
}
for(i=0;i<n;i++)for(j=0;j<n;j++) sum+=c[i][j];
endTime=clock();
time=endTime-startTime;
printf("sum=%lld time=%dms\n",sum,time);
}
int main()
{
int n, num_thread;
while(scanf("%d%d",&n,&num_thread)!=EOF)
{
solve(n,num_thread);
}
return 0;
}
2.分析矩阵相乘程序的执行时间、加速比和效率:方阵阶固定为1000,节点数分别取1、2、4、8、16和32时,为减少误差,每项实验进行5次,取平均值作为实验结果。

答:串行执行时程序的执行时间为:T = 15.062s
加速比=顺序执行时间/并行执行时间
效率=加速比/节点数
表1 不同节点数下程序的执行时间(秒)
节点数
1 2 4 8 16 32
实验结果
第1次16.640 8.172 4.078 2.125 1.093 0.594
第2次16.422 8.156 4.172 2.141 1.078 0.578
第3次16.406 8.266 4.078 2.125 1.094 0.563
第4次16.781 8.172 4.079 2.109 1.094 0.563
第5次16.422 8.171 4.078 2.125 1.093 0.578
平均值16.5342 8.1874 4.0970 2.1250 1.0904 0.5752 Array
图1 不同节点数下程序的执行时间
图2 不同节点数下程序的加速比
图3 不同节点数下程序的效率
执行时间的分析:
随着节点数的增加,程序的执行时间减少,大概可以从结果中得出,随着节点书的增加一倍,执行时间减少一半
加速比的分析:
随着节点数的增加,程序的加速比增加,大概可以从结果中得出,随着节点书的增加一倍,加速相应的增加接近一倍
效率的分析:
随着节点数的增加,程序的效率逐渐减少
3.分析矩阵相乘程序的问题规模与效率的关系:固定节点数为4,让方阵阶从200到1600之间变化,每隔100取一个值。

(为了减少时间,每项实验可只执行1次)
答:
表2 相同节点数下不同问题规模程序的执行时间与效率
方阵阶数并行执
行时间
串行执
行时间
效率
200 0.015 0.047 0.783333 300 0.016 0.109 1.703125 400 0.063 0.297 1.178571 500 0.156 0.657 1.052885 600 0.406 1.64 1.009852 700 0.907 3.578 0.986218 800 1.609 6.36 0.988191 900 2.578 10.109 0.980314 1000 3.812 14.891 0.976587 1100 5.39 21.032 0.97551 1200 7.344 28.734 0.978145 1300 9.688 37.937 0.978969 1400 12.422 48.64 0.978908 1500 15.656 60.938 0.973077 1600 19.234 74.829 0.972614
图3.1 不同问题规模下程序的效率
问题规模与效率的关系分析:
随着问题规模的增加,程序的效率趋于稳定,但是略微有点下降。

相关文档
最新文档