循环中缺少错误(OpenMP with C)
问题描述:
int count1(testcase *testcases, int n) {
int i;
int count = 0;
#pragma omp parallel for
for (i = 0; i < n; ++i) {
if (test(testcases[i]) == true) {
++count;
}
}
return count;
}
有点不寻常的问题,即似乎没有问题。 自学OpenMP for C,这是关于我正在阅读的主题的PDF文档。循环中缺少错误(OpenMP with C)
作者暗示代码存在一些问题。给定n个测试案例,我们有一些功能测试可以对案例进行处理,并返回一个布尔值,指示测试是否成功。这段代码应该计算测试次数。作者说,它不正确 - 我只是不明白为什么。一直以来,我一直试图围绕它思考这个问题,这可能很简单。
我已经试图代码的这个用0和1的阵列的示例版本和由表达式检查,如果它是1和计数该取代
test(testcases[i]) == true
。但是,它正确地计算了我的1。错误在哪里?
答
这是处理,这段代码可以执行得很好,但问题是count变量,它在并行区域外(也称为循环)声明,然后在并行区域内增加。所以计数增加并行运行,这就产生了一个问题,因为如果2个或更多线程同时尝试增加计数,因为相信我会发生这种情况。然后奇怪的事情会开始发生。
变量存储在内存右侧,所以为了增加变量的值,我们需要从内存中读取它(当前值),在CPU中增加它并将其写回。现在我们并行运行该序列中,从而作为一个示例中,这有时会发生(记住线程并行运行):在存储器
- 计数= 2
- 线程1读取计数(2)
- 线程2读取数(2)
- 线程1度的增加和写回计数内存变量(3)
- 同样的事情不会线程2现在(写回3)
所以我n内存我们在count变量中有3的值,但是由于两个线程被执行,它应该是4.这就是为什么这个代码不会总是工作。而这只是可能发生的事情之一。这就是为什么我们知道关键部分,信号量,互斥,...希望这有助于。
正确的做法是'#pragma omp parallel for reduction(+:count)'。试试这个,看看你能否让它有所作为。你可以从删除条件测试开始,然后递增count。它应该等于'n'。 –