我正在使用信号矩阵,我的目标是计算一行中所有元素的总和。矩阵由以下结构表示:
typedef struct matrix {
float *data;
int rows;
int cols;
int leading_dim;
} matrix;
我必须提到矩阵以列主要顺序(http://en.wikipedia.org/wiki/Row-major_order#Column-major_order)存储,这应该解释用于检索正确索引的公式column * tan_hd.rows + row
。
for(int row = 0; row < tan_hd.rows; row++) {
float sum = 0.0;
#pragma omp parallel for reduction(+:sum)
for(int column = 0; column < tan_hd.cols; column++) {
sum += tan_hd.data[column * tan_hd.rows + row];
}
printf("row %d: %f", row, sum);
}
如果没有OpenMP pragma,交付的结果是正确的,如下所示:
row 0: 8172539.500000 row 1: 8194582.000000
如上所述,只要添加#pragma omp...
,就会返回不同的(错误的)结果:
row 0: 8085544.000000 row 1: 8107186.000000
根据我的理解,reduction(+:sum)
为每个线程创建sum
的私有副本,并在完成循环后,将这些部分结果相加并再次写回全局变量sum
。是什么,我做错了?
感谢您的建议!
答案 0 :(得分:1)
通过重写代码来实现它:
for(int row = 0; row < tan_hd.rows; row++) {
float sum = 0.0, c = 0.0;
#pragma omp parallel for reduction(+:sum, +:c)
for(int column = 0; column < tan_hd.cols; column++) {
float y = tan_hd.data[column * tan_hd.rows + row] - c;
float t = sum + y;
c = (t - sum) - y;
sum = t;
}
sum = sum - c;
printf("row %d: %f", row, sum);
}
您还可以将所有float
切换为double
以获得更高的精度,但由于您的数组是float
数组,因此应该只有不同数量的显着数字。结束。