OpenMP 矩阵乘法嵌套循环

Posted

技术标签:

【中文标题】OpenMP 矩阵乘法嵌套循环【英文标题】:OpenMP matrix multiplication nested loops 【发布时间】:2012-11-14 13:40:22 【问题描述】:

这是一个矩阵乘法代码,其中一个 i 循环并行化,另一个 j 循环并行化。对于这两个版本,C 数组的值都是正确的(我已经用小矩阵大小进行了测试)。与其他相比也没有性能提升。

谁能告诉我这两个版本有什么区别?无论矩阵大小如何,数组C 在两个版本中都准确吗?提前致谢

void mat_multiply ( void )

    int t;
    int i, j, k;    
    #pragma omp parallel for private(k) // parallelize i loop
    for(i = 0; i < dimension; i++)
    
        for(j = 0; j < dimension; j++) 
        
            for(k = 0; k < dimension; k++)
            
                C[dimension*i+j] += A[dimension*i+k] *  B[dimension*k+j];       
            
        
    
 

 void mat_multiply ( void )
 
     int t;
     int i, j, k;   

     for(i = 0; i < dimension; i++)
     
         #pragma omp parallel for private(k) // parallelize j loop
         for(j = 0; j < dimension; j++) 
         
             for(k = 0; k < dimension; k++)
             
                 C[dimension*i+j] += A[dimension*i+k] *  B[dimension*k+j];      
             
         
     
 

【问题讨论】:

【参考方案1】:

起初,似乎第一个版本的线程创建开销较低,因为它只会创建一次线程。而在第二个版本中,线程似乎将被创建dimension 次。

但是根据this

人们可能会担心在内部创建新线程 环形。不用担心,GCC 中的 libgomp 足够聪明,实际上只 创建线程一次。团队完成工作后,线程 被送回“码头”,等待新的工作。

也就是说,clone系统调用被执行的次数 正好等于最大并发线程数。这 并行指令与 pthread_create 的组合不一样 和 pthread_join。

在第一个版本中,您应该保证变量j 也是私有的。

您可以只使用一种嵌套循环并行化的方法,而不是使用两种方法。在OpenMP 3.0中,嵌套循环的并行化可以通过for指令中的collapse子句来处理,即:

void mat_multiply ( void ) 
   
    #pragma omp parallel for collapse(2)
    for(int i = 0; i < dimension; i++)
      for(int j = 0; j < dimension; j++)
        for(int k = 0; k < dimension; k++)
            C[dimension*i+j] += A[dimension*i+k] *  B[dimension*k+j];        
  

顺便说一句:看看块方法,您可以看到一个示例 here(从幻灯片 62 开始)。

【讨论】:

以上是关于OpenMP 矩阵乘法嵌套循环的主要内容,如果未能解决你的问题,请参考以下文章

使用嵌套的 for 循环实现矩阵向量乘法的标量、行变体

基于OpenMP的矩阵乘法实现及效率提升分析

C++ openMP 并行矩阵乘法

OpenMP 矩阵向量乘法仅在一个线程上执行

在矩阵乘法中使用 C++2011 线程而不是 OpenMP 时出现异常加速

使用 openmp 并行化矩阵乘法并使用 avx2 进行矢量化