QImage и openmp при обновлении отображения изображений

В Qt 5.5 для Mac я пытаюсь ускорить вычисление буфера изображения и его отображения с помощью QImage. Я использовал директивы openMP, но понял, что это мешает отображению QImage.

Вот код:

int = 65535    
newPaintImage = new QImage(naxis1, naxis2, QImage::Format_ARGB32 );
#pragma omp parallel for
for ( int ii = 0; ii < nPixels; ++ii )
{
    cred = (int) 255 * red16[ii] / range;
    cgreen = (int) 255 * green16[ii] / range;
    cblue = (int) 255 * blue16[ii] / range;     

    QRgb argb = qRgba( cred, cgreen, cblue, 255);
    QRgb* rowData = (QRgb*) newPaintImage->scanLine(ii/naxis1);
    rowData[ii%naxis1] = argb;
}
newPaintWidget = new PaintWidget(newPaintImage, naxis1, naxis2);

В приведенном выше коде nPixels - это общее количество пикселей в изображении, а red16, green16 и blue16 - это трехцветные каналы моих изображений. Их размер равен nPixels. Значения naxis1 и naxis2 - это ширина и высота (в пикселях).

Обратите внимание на директиву pragma для распараллеливания цикла for. Когда я использую его, на моем изображении появляются зашифрованные линии, и любое обновление изображения меняет результаты. Когда я не использую директиву pragma, так что используется только один поток, мое изображение в порядке, как и ожидалось. Я меняю и обновляю буфер с таким распараллеливанием, и это портит отображение.

Есть ли способ лучше? Например, убедиться, что мои потоки завершили работу, а затем обновить отображение в paintEvent моего объекта Qt? Или что-то связанное с тем, как QImage распределяется по потокам? ...

Спасибо


person Wall-E    schedule 14.10.2015    source источник
comment
Попробуйте добавить private(cred, cgreen, cblue) в вашу прагму OpenMP. Не уверен, что этого хватит, но однозначно нужно.   -  person Gilles    schedule 14.10.2015
comment
Чем больше я это читаю, тем больше уверен, что #pragma omp parallel for private(cred, cgreen, cblue) должно хватить для параллельной работы вашего кода. Не уверен, что это будет быстрее, поскольку ваш код в основном привязан к памяти.   -  person Gilles    schedule 14.10.2015
comment
@gilles Хорошо, я только что попробовал это с #pragma omp parallel for private(cred, cgreen, cblue), и у меня возникла ошибка компиляции: error: expected variable name #pragma omp parallel for private(cred, cgreen, cblue) Я совершенно не разбираюсь в этих директивах. Любая идея?   -  person Wall-E    schedule 14.10.2015
comment
@gilles Все заработало! Credit, cgreen, cblue были частными для класса. Итак, директиве требовалось следующее: int cred2, cgreen2, cblue2; #pragma omp parallel for private(cred2, cgreen2, cblue2) Я отправляю исправленный код. Спасибо за вашу помощь! Это было быстро!!   -  person Wall-E    schedule 14.10.2015


Ответы (1)


Благодаря предложению в комментарии я исправил это. Предложение pragma private было необходимо для определения частных переменных, с которыми нужно работать.

int cred2, cgreen2, cblue2   
#pragma omp parallel for private(cred2, cgreen2, cblue2)
for ( int ii = 0; ii < nPixels; ++ii )
{
    cred2 = (int) 255 * red16[ii] / range;
    cgreen2 = (int) 255 * green16[ii] / range;
    cblue2 = (int) 255 * blue16[ii] / range;
    QRgb argb = qRgba( cred2, cgreen2, cblue2, 255);
    QRgb* rowData = (QRgb*) newPaintImage->scanLine(ii/naxis1);
    rowData[ii%naxis1] = argb;
}
newPaintWidget = new PaintWidget(newPaintImage, naxis1, naxis2);

И да, это значительно быстрее! Это используется с некоторыми сигналами / слотами QSlider, которые выполняют растяжение контраста. Здесь я упростил код. Фактически, range меняется, а не фиксируется и, например, red16[ii] - это (red16[ii] - minValue), где minValue изменяется с некоторыми QSlider.

person Wall-E    schedule 14.10.2015