OpenMP用于矩阵乘法
OpenMP for matrix multiplication
我是OpenMP新手,正在拼命学习。我试图在visual studio 2012中编写c++示例代码来实现矩阵乘法。我希望有OpenMP经验的人可以看看这段代码,并帮助我获得最终的速度/并行化:
#include <iostream>
#include <stdlib.h>
#include <omp.h>
#include <random>
using namespace std;
#define NUM_THREADS 4
// Program Variables
double** A;
double** B;
double** C;
double t_Start;
double t_Stop;
int Am;
int An;
int Bm;
int Bn;
// Program Functions
void Get_Matrix();
void Mat_Mult_Serial();
void Mat_Mult_Parallel();
void Delete_Matrix();
int main()
{
printf("Matrix Multiplication Programnn");
cout << "Enter Size of Matrix A: ";
cin >> Am >> An;
cout << "Enter Size of Matrix B: ";
cin >> Bm >> Bn;
Get_Matrix();
Mat_Mult_Serial();
Mat_Mult_Parallel();
system("pause");
return 0;
}
void Get_Matrix()
{
A = new double*[Am];
B = new double*[Bm];
C = new double*[Am];
for ( int i=0; i<Am; i++ ){A[i] = new double[An];}
for ( int i=0; i<Bm; i++ ){B[i] = new double[Bn];}
for ( int i=0; i<Am; i++ ){C[i] = new double[Bn]; }
for ( int i=0; i<Am; i++ )
{
for ( int j=0; j<An; j++ )
{
A[i][j]= rand() % 10 + 1;
}
}
for ( int i=0; i<Bm; i++ )
{
for ( int j=0; j<Bn; j++ )
{
B[i][j]= rand() % 10 + 1;
}
}
printf("Matrix Create Complete.n");
}
void Mat_Mult_Serial()
{
t_Start = omp_get_wtime();
for ( int i=0; i<Am; i++ )
{
for ( int j=0; j<Bn; j++ )
{
double temp = 0;
for ( int k=0; k<An; k++ )
{
temp += A[i][k]*B[k][j];
}
}
}
t_Stop = omp_get_wtime() - t_Start;
cout << "Serial Multiplication Time: " << t_Stop << " seconds" << endl;
}
void Mat_Mult_Parallel()
{
int i,j,k;
t_Start = omp_get_wtime();
omp_set_num_threads(NUM_THREADS);
#pragma omp parallel for private(i,j,k) schedule(dynamic)
for ( i=0; i<Am; i++ )
{
for ( j=0; j<Bn; j++ )
{
//double temp = 0;
for ( k=0; k<An; k++ )
{
C[i][j] += A[i][k]*B[k][j];
}
}
}
t_Stop = omp_get_wtime() - t_Start;
cout << "Parallel Multiplication Time: " << t_Stop << " seconds." << endl;
}
void Delete_Matrix()
{
for ( int i=0; i<Am; i++ ){ delete [] A[i]; }
for ( int i=0; i<Bm; i++ ){ delete [] B[i]; }
for ( int i=0; i<Am; i++ ){ delete [] C[i]; }
delete [] A;
delete [] B;
delete [] B;
}
我的例子是基于我为并行教学创建的矩阵类。如果你感兴趣,请随时与我联系。有几种方法可以加速矩阵乘法:
<<h3>存储/h3>使用按行主序排列的一维数组,以便更快地访问元素。
可以用A[i * An + j]
使用循环不变优化
for (int i = 0; i < m; i ++)
for (int j = 0; j < p; j ++)
{
Scalar sigma = C(i, j);
for (int k = 0; k < n; k ++)
sigma += (*this)(i, k) * B(k, j);
C(i, j) = sigma;
}
这可以防止在最内部的循环中多次重新计算C(i,j)。
改变循环顺序"for k <-> for i"
for (int i = 0; i < m; i ++)
for (int k = 0; k < n; k ++)
{
Aik = (*this)(i, k);
for (int j = 0; j < p; j ++)
C(i, j) += Aik * B(k, j);
}
这允许使用空间数据局部性
使用循环阻塞/平铺
for(int ii = 0; ii < m; ii += block_size)
for(int jj = 0; jj < p; jj += block_size)
for(int kk = 0; kk < n; kk += block_size)
#pragma omp parallel for // I think this is the best place for this case
for(int i = ii; i < ii + block_size; i ++)
for(int k = kk; k < kk + block_size; k ++)
{
Scalar Aik = (*this)(i, k);
for(int j = jj; j < jj + block_size; j ++)
C(i, j) += Aik * B(k, j);
}
这可以使用更好的时间数据局部性。最佳的block_size取决于你的体系结构和矩阵大小。
然后并行化!
一般来说,#pragma omp parallel for应该在最外层的循环中执行。也许在前两个外部环路上使用两个平行环路可以得到更好的结果。这取决于你使用的架构,矩阵大小……你必须测试!由于矩阵乘法具有静态工作负载,因此我将使用静态调度。
莫尔优化!
你可以做循环巢优化。您可以对代码进行矢量化。你可以看看BLAS是怎么做的。
我对OpenMP很陌生,这段代码很有指导意义。然而,我在串行版本中发现了一个错误,这使得它比并行版本具有不公平的速度优势。
不像在并行版本中那样写C[i][j] += A[i][k]*B[k][j];
,而是在串行版本中写temp += A[i][k]*B[k][j];
。这要快得多(但不能帮助您计算C矩阵)。所以你不是在比较苹果和苹果,这使得并行代码看起来比较慢。当我修复这一行并在我的笔记本电脑上运行它(它允许2个线程)时,并行版本的速度几乎是两倍。不坏!
相关文章:
- 为什么 openmp 的并行不适用于矢量化色彩空间转换?
- OpenMP 内部的函数调用用于循环
- 为什么Visual Studio 2019不支持用于减少Openmp的关键字"max"?
- 用于 OpenMP 4.5 卸载到 (GPU) 设备的 NVPTX GCC (9.0.0/trunk) 找不到 libg
- 用于在一维数组上嵌套循环操作的正确 openmp 指令
- OpenMP 并行用于 cout 顺序
- tbb parallel_reduce 用于 OpenMP 缩减的片段
- 用于C++对象数组上循环的OpenMP
- 增加OpenMP中用于进度报告的共享循环计数器
- 将OpenMP应用于C++中的特定嵌套循环
- C++中用于嵌套循环的OpenMP编程的锁定策略
- 用于在C++中使用OpenMP的算法库
- 如何将 OpenMP 用于我的代码
- 用于加速器的OpenMP 4.0:Nvidia GPU目标
- GCC OpenMP 并行用于减少比 Visual Studio 慢得多
- openMP 用于循环增量语句处理
- openMP 嵌套并行用于循环与内部并行
- OpenMP vs OpenCL 用于计算机视觉
- c++openmp,用于循环执行期间的循环最大减少值
- openmp并行用于具有两个或多个缩减的循环