[英]Why does inserting a printf statement make my function work correctly?
这是我的代码的基本前提:
while(norm_of_error > tol){
#pragma omp parallel for
for(i = 1; i <= N*N; i++){
//printf("thread id: %d\n",omp_get_thread_num());
:
int val = based on i
:
#pragma omp critical
x[i-1] = val;
}
#pragma omp barrier
iter++;
}
简而言之,我使用Jacobi迭代方法求解Ax = b。 我的问题是,在取消注释printf()
语句的情况下, norm_of_error
趋于零并且while循环结束。 但是,通过简单地注释掉printf()
语句,就不会发生这种情况。 任何人都可以给我一个提示,为什么printf()
语句有任何影响? 我猜这个问题与omp_get_thread_num()的调用有关,但我不明白为什么会有任何区别。
编辑:我将printf()
语句更改为printf("hi\\n");
并且代码有效。 注释出来,代码不起作用。
与printf()
语句一起使用但在删除时失败的代码通常是某些无效操作的标志,这些操作会影响某个程序中的内存(例如,从数组的末尾掉下来,取消引用NULL
等)。 行为不当的代码可能完全在程序的其他部分(例如,不在包含printf()
语句的函数内)
当违规的printf()
声明显然是无辜的,并且没有任何可能影响其他代码行为的副作用(例如printf("Hi\\n")
)时,这更有可能发生。
原因是额外的printf()
存在实际上影响了整个程序的内存布局。 因此,违规代码(可能在程序中某些完全不相关的部分)仍会覆盖内存,但结果会发生变化(例如,覆盖某些数据,允许程序更改,而不是导致操作系统终止的某些内存区域)该程序)。
无论代码是否为多线程,都是如此。
如果没有完整的代码来说明问题(即其他人可以编译,构建和运行以获得相同症状的小样本),则不可能更具体。
您还没有发布您的代码,因此我们无法确切知道,但这通常是因为您尝试在线程之间共享数据而未充分指示要共享数据。
删除printf
后,程序将数据加载到寄存器中,当它再次需要数据时,它会记住寄存器中的值而不是再次从内存中取出它,因此它看不到其他线程可能发生的任何更改取得了。
使用printf
,你的程序不会将数据保存在寄存器中 - 也许它不能以这种方式使用寄存器,或者它无法确定函数调用无法更改数据(当然,它只是printf
,但它可能不是特殊的,即使它是,编译器更好地找到可能允许printf
更改数据的漏洞) - 所以它在调用printf
后重新读取内存中的数据,因此可以看到在其他线程中进行的任何先前更改。
printf
可以改变的另一个方面是时间:与计算相比,I / O语句非常慢,并且I / O库中可能会发生一些同步; 您的print
可能会起到阻止竞争条件发生的伪障碍的作用。
请记住,C和C ++是不同的语言 。
comp.lang.c常见问题列表·问题16.5
问:这个程序在一台机器上运行完美,但我在另一台机器上得到了奇怪的结果。 更奇怪的是,添加或删除调试打印输出会改变症状......
答:很多事情都可能出错; 这里有一些比较常见的事情要检查:
- 未初始化的局部变量[脚注](另见问题7.1)
- 整数溢出,特别是在16位机器上,特别是在执行像* b / c这样的事情时的中间结果(另见问题3.14)
- 未定义的评估顺序(见问题3.1至3.4)
- 省略外部函数的声明,特别是那些返回int以外的函数,或者有``narrow''或变量参数的函数(参见问题1.25,11.3,14.2和15.1)
- 解除引用的空指针(参见第5节)
- 不正确的malloc /免费使用:假设malloc的内存包含0,假设释放存储持续存在,释放两次,破坏malloc竞技场(另见问题7.19和7.20)
- 指针问题一般(另见问题16.7和16.8)
- printf格式和参数之间不匹配,尤其是尝试使用%d打印长整数(参见问题12.7和12.9)
- 尝试分配比unsigned int更多的内存可以计算,特别是在内存有限的机器上(参见问题7.16和19.23)
- 数组边界问题,特别是小的临时缓冲区,可能用于使用sprintf构造字符串[脚注](另见问题7.1,12.21和19.28)
- 关于typedef映射的无效假设,尤其是size_t(参见问题7.15)
- 浮点问题(见问题14.1和14.4a)
- 你认为的任何东西都巧妙地利用了你认为特定系统生成代码的方式
正确使用函数原型可以捕获其中的几个问题; 皮棉会抓到几个。 另见问题16.3,16.4和18.4。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.