繁体   English   中英

OpenMP 矩阵乘法嵌套循环

[英]OpenMP matrix multiplication nested loops

这是一个矩阵乘法代码,其中一个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];      
             }
         }
     }
 }

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

但是按照这个

人们可能会担心在内循环中创建新线程。 不用担心,GCC 中的 libgomp 足够聪明,实际上只创建一次线程。 一旦团队完成其工作,线程将返回到“停靠”,等待新的工作要做。

也就是说,clone系统调用的执行次数正好等于最大并发线程数。 parallel 指令与 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];        
  }

顺便说一句:看看块方法,你可以在这里看到一个例子(从幻灯片 62 开始)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM