[英]Performance of matrix multiplications remains unchanged with OpenMP in C++
auto t1 = chrono::steady_clock::now();
#pragma omp parallel
{
for(int i=0;i<n;i++)
{
#pragma omp for collapse(2)
for(int j=0;j<n;j++)
{
for(int k=0;k<n;k++)
{
C[i][j]+=A[i][k]*B[k][j];
}
}
}
}
auto t2 = chrono::steady_clock::now();
auto t = std::chrono::duration_cast<chrono::microseconds>( t2 - t1 ).count();
有和没有并行化,变量t保持相当恒定。 我不确定为什么会这样。 同样,有时t输出为0。我面临的另一个问题是,如果我将n的值增加到500,那么编译器将无法运行该程序。(这里我取n = 100)我我在GNU GCC编译器中使用code :: blocks。
提议的OpenMP并行化是不正确的,并且可能导致错误的结果。 当指定collapse(2)
,线程“同时”执行(j,k)迭代。 如果两个(或更多)线程在相同的j上但不同的k上工作,则它们将A[i][k]*B[k][j]
的结果累加到相同的数组位置C[i][j]
。 这就是所谓的竞争条件,即“两个或多个线程可以访问共享数据,并且它们试图同时更改共享数据”( 什么是竞争条件? )。 尽管代码对OpenMP无效,但数据争用并不一定会导致错误的结果,并且可能会根据多个因素(调度,编译器实现,线程数等)产生错误的结果。 为了解决上面代码中的问题,OpenMP提供了reduction
条款:
#pragma omp parallel
{
for(int i=0;i<n;i++) {
#pragma omp for collapse(2) reduction(+:C)
for(int j=0;j<n;j++) {
for(int k=0;k<n;k++) {
C[i][j]+=A[i][k]*B[k][j];
因此,“将在每个隐式任务(...)中创建一个私有副本,并使用reducer-identifier的初始化值对其进行初始化。在该区域结束之后,原始列表项将使用私有副本的值进行更新。使用与归约标识符关联的组合器”( http://www.openmp.org/wp-content/uploads/openmp-4.5.pdf )。 请注意,自OpenMP 4.5起,该标准直接支持C语言中数组的缩减(请检查编译器是否支持它,否则,有一些旧的手动方法可以实现,即OpenMp中的数组缩减 )。
但是,对于给定的代码,应该避免最内层循环的并行化可能更合适,这样根本就不需要减少操作:
#pragma omp parallel
{
#pragma omp for collapse(2)
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
for(int k=0;k<n;k++) {
C[i][j]+=A[i][k]*B[k][j];
对于较小的矩阵和/或少量的线程,串行可以比OpenMP版本更快。 在使用最多16个内核,n = 1000的Intel机器上,当激活-O3优化时,GNU编译器v6.1的收支平衡约为4个内核,而使用-O0编译的收支平衡约为2个内核。 为了清楚起见,我报告了我测量的性能:
Serial 418020
----------- WRONG ORIG -- +REDUCTION -- OUTER.COLLAPSE -- OUTER.NOCOLLAPSE -
OpenMP-1 1924950 2841993 1450686 1455989
OpenMP-2 988743 2446098 747333 745830
OpenMP-4 515266 3182262 396524 387671
OpenMP-8 280285 5510023 219506 211913
OpenMP-16 2227567 10807828 150277 123368
减少使用会导致性能损失(加速倒退)。 外部并行化(不折叠或不折叠)是最佳选择。
关于大型矩阵的故障,可能的原因与可用堆栈的大小有关。 尝试同时扩大系统和OpenMP堆栈的大小,即
ulimit -s unlimited
export OMP_STACKSIZE=10000000
collapse
指令实际上可能对此负责,因为索引j
是使用divide / mod操作重新创建的。
您尝试没有collapse
吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.