OpenMP优化?

时间:2011-07-21 17:20:06

标签: c gcc openmp

我无法弄清楚为什么这个功能的性能如此糟糕。我有一个核心2 Duo机器,我知道它只创造2个trheads所以它不是一个太多线程的问题。我希望结果更接近我的pthread结果。

这些是我的编译标志(故意不做任何优化标志) gcc -fopenmp -lpthread -std = c99 matrixMul.c -o matrixMul

这些是我的结果

Sequential matrix multiply: 2.344972
Pthread    matrix multiply: 1.390983
OpenMP     matrix multiply: 2.655910
CUDA       matrix multiply: 0.055871
Pthread Test PASSED
OpenMP  Test PASSED
CUDA    Test PASSED

void openMPMultiply(Matrix* a, Matrix* b, Matrix* p)
{
  //int i,j,k;
  memset(*p, 0, sizeof(Matrix));
  int   tid, nthreads, i, j, k, chunk;
  #pragma omp parallel shared(a,b,p,nthreads,chunk) private(tid,i,j,k)
  {
        tid = omp_get_thread_num();
        if (tid == 0)
        {
          nthreads = omp_get_num_threads();
        }
        chunk = 20;
        //   #pragma omp parallel for private(i, j, k)
        #pragma omp for schedule (static, chunk)
        for(i = 0; i < HEIGHT; i++)
        {
          //printf("Thread=%d did row=%d\n",tid,i);
                for(j = 0; j < WIDTH; j++)
                {
                        //#pragma omp parallel for
                        for(k = 0; k < KHEIGHT ; k++)
                                (*p)[i][j] += (*a)[i][k] * (*b)[k][j];
                }
        }
  }
}

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

由于矩阵乘法是一个令人尴尬的并行,它的加速应该在双核上接近2。由于减少了高速缓存未命中,矩阵乘法甚至通常显示超线性加速(在双核上大于2)。通过查看代码我没有看到明显的错误,但是出了点问题。以下是我的建议:

  1. 只需仔细检查工作线程数。在您的情况下,应创建2个线程。或者,尝试通过调用omp_set_num_threads进行设置。另外,看看是否充分利用了2个内核(即Windows上100%的CPU利用率,Linux上的200%)。

  2. 删除不必要的nthreadschunk以清理代码。这些可以在平行部分之外制备。但即便如此,也不应该损害加速。

  3. 矩阵是正方形(即HEIGHT == WIDTH == KHEIGHT)?如果它不是方阵,则可能存在工作负载不平衡,这可能会损害加速。但是,考虑到pthread的加速(大约1.6,这对我来说也很奇怪),我认为工作量不平衡太多了。

  4. 尝试使用默认的静态计划:不要指定chunk,只需写#pragma omp for

  5. 我最好的猜测是Matrix的结构可能会有问题。 Matrix究竟是什么样的?在最坏的情况下,虚假共享可能会严重影响性能。但是,在这种简单的矩阵乘法中,虚假共享应该不是一个大问题。 (如果你不知道细节,我可以解释更多细节)。

  6. 虽然您已注释掉,但请勿将#pragma omp parallel for放在for-k,这会导致嵌套并行循环。在矩阵乘法中,由于最外层的循环是可并行化的,所以绝对是浪费。

  7. 最后,尝试运行以下非常简单的OpenMP矩阵乘法代码,并查看加速:

    double A[N][N], B[N][N], C[N][N];
    #pragma omp parallel for
    for (int row = 0; row < N; ++row)
      for (int col = 0; col < N; ++col)
        for (int k = 0; k < N; ++k)
          C[row][col] += A[row][k]*B[k][col];