Распараллелить вложенные циклы, используя OpenMP - PullRequest
0 голосов
/ 07 ноября 2018

Я пытался распараллелить вложенный цикл, используя OpenMP, но я не уверен, что это правильный способ сделать это. Вот часть кода, имеющая вложенные циклы. Это просто общий код. Я даю noofrecords как 50k, это занимает много времени даже после распараллеливания. Может кто-нибудь предложить лучшую идею для распараллеливания кода. Я просто распараллеливаю внешний цикл в приведенном ниже коде.

int ctd=0;
#pragma omp parallel for default(none), private(j,k,l), shared(A,B,C,D,ctd)
for(int j=0; j <noofrecords; j++)
{
    for( int k=0; k<noofrecords; k++)
    {
        for( int l=0; l<noofrecords; l++)
        {
            if(condition)
            {
D[ctd].a1=A[i].a1;
ctd++;
              }}}}

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018
  1. создать временный массив a1 типа D.a1 с числом элементов, равным максимальному ожидаемому значению ctd.
  2. создать временный массив a2 из a1 для каждого потока.
  3. Заполните a2 параллельно и используйте ctd2 для подсчета размера a2
  4. Заполните массив a1 в порядке от a2 и добавьте ctd2 к ctd
  5. Запись в D.a1 параллельно с a1

как то так

int ctd=0;
double *a1 = malloc(sizeof *a1 * N);                       //Step 1
#pragma omp parallel
{
  int ctd2 = 0;
  double *a2 = malloc(sizeof *a2 * N);                     //step 2

  #pragma omp for nowait
  for(int j=0; j<noofrecords; j++)
  for(int k=0; k<noofrecords; k++)
  for(int l=0; l<noofrecords; l++)
    if(condition) a2[ctd2++] = A[i].a1;                    //step 3

  #pragma omp for schedule(static) ordered
  for(int i=0; i<omp_get_num_threads(); i++)
    #pragma omp ordered
    memcpy(&a1[ctd], a2, sizeof *a1 * ctd2), ctd += ctd2;  //step 4

  #pragma omp for
  for(int j=0; j<ctd; j++) D[j].a1 = a1[j];                // step 5
  free(a2);
}
free(a1);

N должен быть максимальный размер, который вы ожидаете ctd. Недостатком памяти в этом методе является то, что a2 выделяется с размером N, который может быть слишком большим. Динамический вектор, такой как std::vector в C ++ или GArray в glib, будет более эффективным с точки зрения памяти.

0 голосов
/ 07 ноября 2018

Вы можете использовать условие коллапса, в вашем случае у вас есть 3 последовательных цикла for, поэтому это будет что-то вроде: #pragma omp параллельный по умолчанию (нет), частный (j, k, l), общий (A, B, C, D, ctd) collapse (3)

Это будет работать, если циклы for являются последовательными, а код находится в самом внутреннем цикле (это относится и к коду, который вы разместили). Это не намного больше, чем ваш максимальный счет потока, ускорение не будет впечатляющим. Если он работает медленно даже параллельно, это, вероятно, означает, что узкое место - это не ваша вычислительная мощность (более вероятно, что оперативная память уже работает на 100%).

Кроме того, я не уверен, что вы действительно хотите этого частного (j, k, l) ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...