矩阵乘法的OpenMP性能问题

我遇到使用OpenMp的性能问题。 我试图测试不使用OpenMP和使用OpenMP的应用程序的单线程程序的结果。 通过查看在线比较矩阵链乘法程序的结果,openMP实现速度是其速度的2到3倍,但是我的实现对于两个应用程序来说都是相同的速度。 我正在实施openMP的方式不正确吗? openMP上的任何指针以及如何正确实现它? 任何帮助深表感谢。 提前致谢。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main( int argc , char *argv[] ) 
{
   srand(time(0));
   if ( argc != 2 )
   {
      printf("Usage: %s <size of nxn matrices>n", argv[0]);
      return 1; 
   }

   int n = atoi( argv[1] );
   int a, b;
   double A[n][n], B[n][n], C[n][n];
   FILE *fp;
   fp = fopen("/home/mkj0002/CPE631/Homework2/ArrayTry/matrixResults", "w+"); //For the LeCASA machine

   for(a = 0; a < n; a++)
   {
       for(b = 0; b < n; b++)
       {
          A[a][b] = ((double)rand()/(double)RAND_MAX);  //Number between 0 and 1
          A[a][b] = (double)rand();         //Number between 0 and RAND_MAX
          B[a][b] = ((double)rand()/(double)RAND_MAX);  //Number between 0 and 1
          B[a][b] = (double)rand();         //Number between 0 and RAND_MAX
          C[a][b] = 0.0;
       }
    }

    #pragma omp parallel shared(A,B,C)
    {
        int i,j,k;
        #pragma omp for schedule(guided,n)
        for(i = 0; i < n; ++i)
        {
            for(j = 0; j < n; ++j)
            {
                double sum = 0;
                for(k = 0; k < n; ++k)
                {
                    sum += A[i][k] * B[k][j];
                }

                C[i][j] = sum;
                fprintf(fp,"0.4lf",C[i][j]);
            }
        }
    }

    if(fp)
    {
        fclose(fp);
    }
    fp = NULL;

    return 0;
}                  

(1)不要在并行区域内执行I / O。 当你移动它时,你会看到即时加速并同时写入很多C变量到文件。

(2)完成上述操作之后,您应该将您的调度更改为static因为每个循环都将执行完全相同的计算量,并且不再需要承担花哨调度的开销。

(3)此外,为了更好地利用缓存,你应该交换你的jk循环。 为了看到这一点,设想在当前循环中只访问你的B变量。

for(j = 0; j < n; ++j)
{
    for(k = 0; k < n; ++k)
    {
        B[k][j] += 5.0;
    }
}

您可以看到它如何访问B,就好像它存储在Fortran的列主格式中一样。 更多信息可以在这里找到。 更好的选择是:

for(k = 0; k < n; ++k)
{
    for(j = 0; j < n; ++j)
    {
        B[k][j] += 5.0;
    }
}

回到你的例子中,我们仍然需要处理sum变量。 一个简单的建议就是存储你正在计算的当前sum的行,然后在完成当前循环后保存它们。

结合所有3个步骤,我们得到如下内容:

#pragma omp parallel shared(A,B,C)
{
    int i,j,k;
    double sum[n]; // one for each j

    #pragma omp for schedule(static)
    for(i = 0; i < n; ++i)
    {
        for(j = 0; j < n; ++j)
            sum[j] = 0;

        for(k = 0; k < n; ++k)
        {
            for(j = 0; j < n; ++j)
            {
                sum[j] += A[i][k] * B[k][j];
            }
        }

        for(j = 0; j < n; ++j)
            C[i][j] = sum[j];
    }
}

// perform I/O here using contiguous blocks of C variable

希望有所帮助。

编辑 :按照@ Zboson的建议,在整个程序中简单地删除sum[j]并将其替换为C[i][j]会更容易。

链接地址: http://www.djcxy.com/p/85989.html

上一篇: OpenMP Performance Issues with Matrix Multiplication

下一篇: Multiplying a small matrix inside a bigger matrix in C