循环中缺少错误(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。错误在哪里?

+0

正确的做法是'#pragma omp parallel for reduction(+:count)'。试试这个,看看你能否让它有所作为。你可以从删除条件测试开始,然后递增count。它应该等于'n'。 –

这是处理,这段代码可以执行得很好,但问题是count变量,它在并行区域外(也称为循环)声明,然后在并行区域内增加。所以计数增加并行运行,这就产生了一个问题,因为如果2个或更多线程同时尝试增加计数,因为相信我会发生这种情况。然后奇怪的事情会开始发生。

变量存储在内存右侧,所以为了增加变量的值,我们需要从内存中读取它(当前值),在CPU中增加它并将其写回。现在我们并行运行该序列中,从而作为一个示例中,这有时会发生(记住线程并行运行):在存储器

  1. 计数= 2
  2. 线程1读取计数(2)
  3. 线程2读取数(2)
  4. 线程1度的增加和写回计数内存变量(3)
  5. 同样的事情不会线程2现在(写回3)

所以我n内存我们在count变量中有3的值,但是由于两个线程被执行,它应该是4.这就是为什么这个代码不会总是工作。而这只是可能发生的事情之一。这就是为什么我们知道关键部分,信号量,互斥,...希望这有助于。

+0

谢谢!我没有想到,但它很有意义。 – jfeis

+1

最重要的是,你应该阅读减刑条款。由于OpenMP在没有效率的情况下不值钱,所以您还应该考虑通过单线程simd减少比通过非simd并行减少可以更高效地实现这样一个简单的情况,但是您可以将它们组合起来。然后有语言特性(可能不是普通的C语言)来实现这一点,这应该在OpenMP之前考虑。 – tim18