OpenMP实现多线程矩阵相乘

在Linux平台上实现单精度浮点的矩阵乘法:

本题使用的软硬件平台

1.【基准程序】输入矩阵A,B,由随机函数产生, 使用串行程序产生正确结果矩阵C,该程序的执行时间为N=4096时, 串行程序时间为588911毫秒。 串行代码如下:

rowMultiplyLine(float row[],float line[],int N,int thread_num=1){float result=0.0;for(int i=0;i<N;i++)result+=row[i]*line[i];return result;}matrixMultiply(float** A,int ArowNum,float** B,int BlineNum,int N,float** R,int thread_num=1){#pragma omp parallel for num_threads(thread_num)for(int row=0;row<ArowNum;row++){for(int line=0;line<BlineNum;line++){float* Bline=new float[N];for(int i=0;i<N;i++)Bline[i]=B[i][line];R[row[line]=rowMultiplyLine(A[row],Bline,N,thread_num);delete[] Bline;}}}

2.【多线程并行化】使用并行方法计算矩阵乘法结果C。 通过OpenMP即可实现多线程并行计算,观看串行代码,调整thread_num的大小,改变计算的线程数,通过表格,可明显的观察到加速。

表2-1 并行矩阵乘法

Thread_num N 误差 计算时间

1 512 0 405ms

1 1024 0 2993ms

1 2048 0 46122ms

1 4096 0 588911ms

2 4096 0 205936ms

4 4096 0 132576ms

8 4096 0 102219ms

12 4096 0 78697ms

24 4096 0 95204ms

请根据上述实验结果,画出两个图。其中图1的X轴为N,Y轴为Thread_num为1时的计算时间,图2的X轴为Thread_num,Y轴为N为4096时的计算时间。

如果你的CPU为多核处理器,你是否观察到计算加速了? 如果观察到计算加速的话,你的处理器核数是 12核 ,图2中Thread_num为 12时,计算性能最好,其加速比是 7.48 。(加速比=多线程执行时间/单线程执行时间)

3.【矩阵分块计算】 每个浮点数占4字节空间,L1 Cache容量是 64 KB,可以放置一个m×m的矩阵小块,其中m= 128 。将整个矩阵分解为这样的小块,每次完成一对小块的计算,以提高Cache的命中率。 提示:

图中n=N/m 计算次序为,因此可以提高Cache的命中率。 分块源码:

rowBlockMultiplyLineBlock(float** rowBlock[],float** lineBlock[],float** blockR, int blockNum, int blockSize,int thread_num=1){ float** tempR=new float*[blockSize]; for(int i=0;i<blockSize; i++) {tempR[i]=new float[blockSize];memset(tempR[i],NULL,sizeof(float)*blockSize); } for(int i=0;i< blockNum;i++) {matrixMultiply(rowBlock[i],blockSize,lineBlock[i],blockSize,blockSize,tempR,thread_num);for(int j=0;j<blockSize;j++)//add the tempR to blockR matrix{for(int k=0;k<blockSize;k++)blockR[j][k]+=tempR[j][k];}} for(int i=0;i<blockSize;i++)delete[] tempR[i]; delete[] tempR;}blockMatrixMultiply( float** A, float** B, float** R_block[512][512], int N, int block_size,int thread_num=1){int bRowNum=N/block_size;int bLineNum=bRowNum;#pragma omp parallel for num_threads(thread_num) schedule(dynamic)for(int row=0;row< bRowNum;row++){float** rowBlock[512]={NULL};for(int i=0;i<N/block_size;i++){rowBlock[i]=new float*[block_size];for(int j=0;j<block_size;j++)rowBlock[i][j]=&A[row*block_size+j][i*block_size];}for(int line=0;line< bLineNum;line++){float** lineBlock[512]={NULL};for(int i=0;i<N/block_size;i++){lineBlock[i]=new float*[block_size];for(int j=0;j<block_size;j++)lineBlock[i][j]=&B[i*block_size+j][line*block_size];}rowBlockMultiplyLineBlock(rowBlock,lineBlock,R_block[row][line],N/block_size, block_size,thread_num);for(int i=0;i<N/block_size;i++)delete[] lineBlock[i];}for(int i=0;i<N/block_size;i++)delete[] rowBlock[i];}}却又小到连一粒嫉妒的沙石也不能容纳

OpenMP实现多线程矩阵相乘

相关文章:

你感兴趣的文章:

标签云: