Qimage setPixel with openmp 并行 for 不起作用

Qimage setPixel with openmp parallel for doesn't work

本文关键字:for 不起作用 并行 openmp setPixel with Qimage      更新时间:2023-10-16

代码在没有并行性的情况下工作,但是当我添加编译指示omp并行时,它不起作用。此外,如果我不添加 setPixel,代码可以完美地与杂注 omp 并行配合使用。所以,我想知道为什么当我尝试在新图像中设置像素时,并行性无法正常工作并以代码 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();
}

QImage::setPixel 不是线程安全的,因为它调用detach() 方法(请在此处查看官方文档)。请记住,QImage使用隐式共享

此外,setPixel()非常。如果你正在寻求性能(就像有人在处理并行实现时通常所做的那样),这不是最好的方法。

在提供的示例中使用scanLine()是正确的方法。

除了 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)