试图理解 OpenMP 浮动数值错误
Trying to understand OpenMP floating numerical errors
我最近开始使用OpenMP对我的图像处理项目进行多线程(MT)。
除了一个函数之外,我对任何函数都没有任何问题(不是计算繁重,但与其他函数中的 int 相比,浮点数操作更多)。
所以首先,假设单线程 (ST) 结果等于图像 X,并且 MT 结果是 Y。
当使用小窗口进行平均时,X == Y,但当窗口变大(5x5)时,X != Y。
因此,我引入了一些"打印"来查看特定像素的值,使用打印繁荣!X == Y 再次。这就是我想了解的。为什么当我打印该代码时,结果又回到了结果 X?
请注意,我试图将浮点模型(英特尔编译器)更改为精确和扩展,并且两个模型都给出了 ST 和 MT 相等,但新的 ST 结果是 Z != X 并且比使用默认浮点模型更长。
编辑:当前代码:
const int tileOffset = 1;
unsigned char** texturePtr = (unsigned char**)texture->getRowPtr();
short** wrkSrcPtr = (short**)wrkSrc->getRowPtr();
short** imFitAPtr = (short**)imFitA->getRowPtr();
short** imFitBPtr = (short**)imFitB->getRowPtr();
short** imFitCPtr = (short**)imFitC->getRowPtr();
// now, compute raw texture value for each pixel using the above plane equations
#pragma omp parallel num_threads(g_options->ompNumberThreads) if(g_options->ompThreaded)
{
#pragma omp for
for ( int i = 0; i < src->getHeight(); i = i + tileOffset ) {
for ( int j = 0; j < src->getWidth(); j = j + tileOffset ) {
bool printPoint = false;
int jVal = 333;
int iVal = 99;
if ( j == jVal && i == src->getHeight() - iVal - 1 ) {
printPoint = true;
printf("nnAt (%d, %d) with Thread %d n", jVal, iVal, omp_get_thread_num());
}
jVal = 343;
iVal = 204;
if ( j == jVal && i == src->getHeight() - iVal - 1 ) {
printPoint = true;
printf("nnAt (%d, %d) with Thread %d n", jVal, iVal, omp_get_thread_num());
}
const int ti = i * tileOffset;
const int tj = j * tileOffset;
const float planeA = imFitAPtr[i][j] / 32000.0f*255.0f;
const float planeB = imFitBPtr[i][j] / 32000.0f*255.0f;
const float planeC = imFitCPtr[i][j] / 32000.0f*255.0f;
float sum2 = 0.0f;
float sum = 0.0f;
int nbSum = 0;
if ( printPoint ) {
printf("Fit (A,B,C) = (%d, %d, %d) and In float (%f, %f, %f) n",
imFitAPtr[i][j], imFitBPtr[i][j], imFitCPtr[i][j],
planeA, planeB, planeC);
}
for ( int ri = i - halfROI; ri <= i + halfROI; ri++ ) {
for ( int rj = j - halfROI; rj <= j + halfROI; rj++ ) {
// sanity checks (image boundaries)
if ( ri < 0 || ri >= src->getHeight() || rj < 0 || rj >= src->getWidth() ) continue;
// eval the local plane at that pixel and compute the residual
const float localPlaneValue = planeA * ( rj - j ) + planeB * ( ri - i ) + planeC;
const float residual = wrkSrcPtr[ri][rj] / 32000.0f*255.0f - localPlaneValue;
const float rr = residual*residual;
if ( printPoint )
printf("Local: %f, residual: %f, resSQ: %f, sum2: %f and sum: %f n ", localPlaneValue, residual, rr, sum2, sum);
sum2 += rr;
sum += residual;
nbSum++;
if ( printPoint )
printf("Add sum2: %f, add sum: %f and nb: %d n ", sum2, sum, nbSum);
}
}
if ( printPoint )
printf("n");
// the texture for that pixel is the stdev
float texVal = 0.0f;
if ( nbSum > 1 ) {
texVal = sqrtf(max(( sum2 - sum * sum / nbSum ) / ( nbSum - 1 ), 0.0f)) * scaling;
if ( texVal > 255.0f ) texVal = 255;
}
texturePtr[ti][tj] = (unsigned char)texVal;
if ( printPoint )
printf("Final value : %d (In float: %f) nn", texturePtr[ti][tj], texVal);
}
}
} // End OMP
使用"外部打印",我注意到平方残差 (rr) 和平方和 (sum2) 是 ST 和 MT 之间不稳定的值。
该问题似乎与Windows下的编译器有关。
此代码使用英特尔编写器 XE 2015 编译。但是当我尝试使用Visual Studio v140时,似乎代码在有和没有OMP的情况下是相似的。
我没有尝试使用较新的英特尔编译器(例如 2017)。在 Linux 下的英特尔作曲家 XE 2015 上不会出现此问题。
相关文章:
- 试图理解 OpenMP 浮动数值错误
- C++ openmp 并行计算计算错误的结果
- OpenMP 会导致内部编译器错误
- Openmp Linux 中的分段错误
- OpenMP 环路阵列访问中的错误共享
- 将 for 循环与嵌套的 while 循环并行化时出现 OpenMP 分段错误
- libcoi_device.so.0 未找到英特尔 19.0.4 OpenMP 5.0 卸载编译错误
- OpenCV 致命错误,同时编译带有 openmp 和 opencv 库的 cpp 文件
- OpenMP卸载到Nvidia错误还原
- 与OpenMP相关的错误,以及使用OpenMP构建LLVM / Clang时C++
- OpenMP *** "..."中的错误:双重释放或损坏(快速顶部):[地址] ***
- OpenMP并行区域中的std::vector push_back会导致错误共享吗
- C++ mac OS X El Capitan上的openmp,Valgrind错误(数据竞赛)
- Eigen & OpenMP : 由于错误共享和线程开销,没有并行化
- OpenMP G++ 错误:折叠的循环未完全嵌套
- 退出 OpenMP 代码时出现分段错误
- 使用布尔数组时出现 Openmp 错误
- 使用 OpenMP 的扩展错误(缓存争用?
- OpenMP Mac OSX Lion c++ 链接器错误 体系结构的未定义符号 x86_64:"_omp_get_thread_num"
- 分段错误 OpenMP 错误