Qimage setPixel с openmp параллельным для не работает - PullRequest
0 голосов
/ 16 мая 2018

Код работает без параллелизма, но когда я добавляю pragma omp parallel, он не работает.Кроме того, код отлично работает с Pragma omp параллельно, если я не добавлю setPixel.Итак, я хотел бы знать, почему параллелизм не работает должным образом и выходит из программы с кодом 255, когда я пытаюсь установить пиксель в новом изображении.Этот код хочет изменить изображение с помощью двух циклов, чтобы изменить каждый пиксель, используя вектор Гаусса.Если что-то не может быть понято, я решу это немедленно.

for (h = 0; h < height; h++){
  QRgb* row = (QRgb*) result->scanLine(h);

  //#pragma omp parallel for schedule(dynamic) num_threads(cores) private (j, auxazul, auxrojo, auxverde) reduction(+:red,green,blue)
  for (w = 0; w < width; w++) {
      red=green=blue=0;

      minj = max((M-w),0);
      supj = min((width+M-w),N);
      for (j=minj; j<supj; j++){
          auxazul = azul [w-M+j][h];
          auxrojo = rojo [w-M+j][h];
          auxverde = verde [w-M+j][h];

          red += vectorGauss[j]*auxrojo;
          green += vectorGauss[j]*auxverde;
          blue += vectorGauss[j]*auxazul;
      }

      red /= 256; green /= 256; blue /= 256;
      //result->setPixel(w,h,QColor(red,green,blue).rgba());
      row[w] = QColor(red,green,blue).rgba();
  }

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Помимо комментария о том, что setPixel является медленным и не безопасным для потоков, у вас в настоящее время есть условие гонки при записи результата

 row[w] = QColor(red,green,blue).rgba(); 

Во-первых, ваш код медленный, потому что вы обращаетесь к своим цветовым матрицам внеэффективный способ памяти.Накачка резьбы сделает эту часть хуже.Учитывая, что вы зацикливаетесь на каждой линии сканирования, вы хотели бы иметь транспонирование ваших цветовых матриц.Что позволяет вам делать:

for (h = 0; h < height; h++){
  QRgb* row = (QRgb*) result->scanLine(h);

  auto azulscan = azul [h];
  auto rojoscan = rojo [h];
  auto verdescan = verde [h];

  for (w = 0; w < width; w++) {
      red=green=blue=0;
      minj = max((M-w),0);
      supj = min((width+M-w),N);
      for (j=minj; j<supj; j++){
          auto auxazul = azulscan [w-M+j];
          auto  auxrojo = rojoscan [w-M+j];
          auto auxverde = verdescan [w-M+j];

          red += vectorGauss[j]*auxrojo;
          green += vectorGauss[j]*auxverde;
          blue += vectorGauss[j]*auxazul;
      }
      row[w] = QColor(red,green,blue).rgba();
  }

}

Я не очень хорошо знаю openmp, но вы хотите иметь один поток на каждую строку развертки, поэтому ваш параллельный цикл должен быть выше первого цикла.Что-то вроде

#pragma omp parallel for whatever
for (h = 0; h < height; h++){
  QRgb* row;

  #pragma omp critical
  {
    row = = (QRgb*) result->scanLine(h);
  }

  .... 

}

Еще один момент.Вы можете использовать std :: inner_product , чтобы вычислить значение цвета в одной строке после транспонирования цветовых входов.

green = std::inner_product(&vectorGauss[minj], &vectorGauss[supj-1]+1, &verdescan[w-M+jmin], &verdescan[w-M+supj]+1)
0 голосов
/ 16 мая 2018

QImage :: setPixel не является потокобезопасным, поскольку вызывает метод detach () (см. Официальную документацию здесь ). Помните, что QImage использует неявное совместное использование .

Кроме того, setPixel () является чрезвычайно медленным . Если вы ищете производительность (как кто-то обычно делает при работе с параллельными реализациями), это не лучший способ.

Использование scanLine () , как вы уже сделали в приведенном примере, является правильным способом сделать это.

...