我对代码进行了如下编辑:
#pragma omp parallel for private(i, piold, err) shared(threshold_err) reduction(+:pi) schedule (static)
{
for (i = 0; i < 10000000000; i++){ //1000000000//705035067
piold = pi;
pi += (((i&1) == false) ? 1.0 : -1.0)/(2*i+1);
err = fabs(pi-piold);
if ( err < threshold_err){
#pragma omp cancel for
}
}
}
pi = 4*pi;我用LLVM3.9/Clang4.0编译它。当我使用一个线程运行它时,我就会使用杂注取消操作获得预期的结果(与非语用取消版本进行检查,会导致更快的运行)。
但是当我使用线程>=2运行它时,程序会进入循环。我正在NUMA机器上运行代码。这是怎么回事?也许取消的条件是不满意的!但是,代码比单线程非实用化取消版本花费的时间更长!!FYI,它运行文件时,OMP_CANCELLATION=false。
我有以下OpenMP代码。我正在使用LLVM-3.9/Clang-4.0编译这段代码。
#pragma omp parallel private(i, piold, err) shared(pi, threshold_err)
{
#pragma omp for reduction(+:pi) schedule (static)
for (i = 0; i < 10000000 ; i++){
piold = pi;
pi += (((i&1) == false) ? 1.0 : -1.0)/(2*i+1);
#pragma omp critical
{
err = fabs(pi-piold);// printf("Err: %0.11f\n", err);
}
if ( err < threshold_err){
printf("Cancelling!\n");
#pragma omp cancel for
}
}
}不幸的是,我认为#pragma omp cancel for并没有终止整个for循环。最后,我打印出了err值,但同样由于并行性,打印哪个值令人困惑。err的最终值小于threshold_err。打印取消是打印,但在一开始的程序,这是令人惊讶的。在那之后,程序一直在运行!
如何确保这是正确的实现?顺便说一下,OMP_CANCELLATION设置为true,一个小测试程序返回相应函数omp_get_cancellation()的'1‘。
发布于 2016-11-13 17:01:48
据我所知,omp取消只是一个中断信号,它会发出通知,以便以后不会创建线程。仍在运行的线程将一直持续到结束。见http://bisqwit.iki.fi/story/howto/openmp/和http://jakascorner.com/blog/2016/08/omp-cancel.html
事实上,在我看来,我认为你的程序产品是可以接受的。但是,一些变量可以保持在较小的范围内。这是我的建议
#include <iostream>
#include <cmath>
#include <iomanip>
int main() {
long double pi = 0.0;
long double threshold_err = 1e-7;
int cancelFre = 0;
#pragma omp parallel shared(pi, threshold_err, cancelFre)
{
#pragma omp for reduction(+:pi) schedule (static)
for (int i = 0; i < 100000000; i++){
long double piold = pi;
pi += (((i&1) == false) ? 1.0 : -1.0)/(2*i+1);
long double err = std::fabs(pi-piold);
if ( err < threshold_err){
#pragma omp cancel for
cancelFre++;
}
}
}
std::cout << std::setprecision(10) << pi * 4 << " " << cancelFre;
return 0;
}发布于 2016-11-16 02:21:41
好吧,所以我解决了。在我上面的代码中,问题就在这里:
err = fabs(pi-piold);
在上面的行中,如果条件发生更改,则在以下条件之前更改pi。同时,多个线程也会这样做。据我所知,这使得程序陷入僵局。
我解决了这个问题,只强制一个线程,主人,做这个检查:
if(omp_get_thread_num()==0){
err = fabs(pi-piold);
if ( err < threshold_err){
#pragma omp cancel for
}
}我本可以使用#pragma omp single,但它给嵌套的语用带来了错误。
在这里,线程数量少(1-4个线程比正常的顺序代码差),性能就会受到影响。在那之后,性能提高了。这不是最好的解决办法,而且肯定有人可以改进这一解决办法。
https://stackoverflow.com/questions/40571582
复制相似问题