3

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

1 回答 1

5

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

但是按照这个

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

也就是说,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];        
  }

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

于 2012-11-27T01:11:33.323 回答