Оптимизации OpenMP? - PullRequest
       12

Оптимизации OpenMP?

0 голосов
/ 21 июля 2011

Я не могу понять, почему производительность этой функции так плоха. У меня есть машина с ядром 2 Duo, и я знаю, что она создает только 2 ствола, так что это не проблема слишком большого количества потоков. Я ожидал, что результаты будут ближе к моим результатам.

это мои флаги компиляции (намеренно не делаю никаких флагов оптимизации) 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 Ответ

2 голосов
/ 22 июля 2011

Поскольку умножение матриц является смущающей параллелью, его ускорение должно быть около 2 на двухъядерном процессоре. Умножение матриц даже обычно показывает суперлинейное ускорение (больше чем 2 на двухъядерном процессоре) из-за уменьшенного количества кеш-пропусков. Я не вижу очевидных ошибок при просмотре вашего кода, но что-то не так. Вот мои предложения:

  1. Просто дважды проверьте количество рабочих потоков. В вашем случае нужно создать 2 темы. Или попробуйте установить, позвонив omp_set_num_threads. Кроме того, проверьте, полностью ли используются два ядра (т. Е. 100% загрузка ЦП в Windows, 200% в Linux).

  2. Очистите свой код, удалив ненужные nthreads и chunk. Они могут быть подготовлены за пределами параллельной секции. Но, даже если так, это не должно повредить ускорению.

  3. Являются ли матрицы квадратными (т. Е. Высота == ширина == высота)? Если это не квадратная матрица, то может возникнуть дисбаланс рабочей нагрузки, который может помешать ускорению. Но, учитывая ускорение pthread (около 1,6, что также странно для меня), я не думаю, что существует слишком большой дисбаланс рабочей нагрузки.

  4. Попробуйте использовать статическое планирование по умолчанию: не указывайте chunk, просто напишите #pragma omp for.

  5. Я думаю, что структура Matrix может быть проблематичной. Как именно выглядит Matrix? В худшем случае ложное совместное использование может значительно снизить производительность. Но при таком простом умножении матриц ложное разделение не должно быть большой проблемой. (Если вы не знаете детали, я могу объяснить более подробно).

  6. Несмотря на то, что вы прокомментировали, никогда не ставьте #pragma omp parallel for на for-k, что приводит к вложенному параллельному циклу. В матричном умножении это абсолютно расточительно, так как внешний цикл наиболее параллелизуем.

Наконец, попробуйте запустить следующий очень простой код умножения матриц 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];
...