Cilk Plus代码的结果取决于工作者的数量



我有一小段代码,我想在升级时将其并行化。我一直在使用Cilk Plus中的cilk_for来运行多线程。问题是,根据工人的数量,我会得到不同的结果。

我读到这可能是由于种族状况造成的,但我不确定代码的具体原因,也不知道如何改善它。此外,我意识到long__float128对这个问题的处理有些过头了,但在升级过程中可能是必要的。

代码:

#include <assert.h>
#include "cilk/cilk.h"
#include <cstring>
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <string>
#include <vector>
using namespace std;
__float128 direct(const vector<double>& Rpct, const vector<unsigned>& values,     double Rbase, double toWin) {
    unsigned count = Rpct.size();
    __float128 sumProb = 0.0;
    __float128 rProb = 0.0;
    long nCombo = static_cast<long>(pow(2, count));
//  for (long j = 0; j < nCombo; ++j) { //over every combination
    cilk_for (long j = 0; j < nCombo; ++j) { //over every combination
        vector<unsigned> binary;
        __float128 prob = 1.0;
        unsigned point = Rbase;
        
        for (unsigned i = 0; i < count; ++i) { //over all the individual events
            long exp = static_cast<long>(pow(2, count-i-1));
            bool odd = (j/exp) %  2;  
            if (odd) {
                binary.push_back(1);
                point += values[i];
                prob *= static_cast<__float128>(Rpct[i]); 
            } else {
                binary.push_back(0);
                prob *= static_cast<__float128>(1.0 - Rpct[i]);  
            }            
        }
        sumProb += prob;
        if (point >= toWin)         rProb += prob;
        assert(sumProb >= rProb);
    }
    //print sumProb
    cout << " sumProb = " << (double)sumProb << endl;
    assert( fabs(1.0 - sumProb) < 0.01);
    return rProb;
}
int main(int argc, char *argv[]) {
    vector<double> Rpct;
    vector<unsigned> value;
    value.assign(20,1);
    Rpct.assign(20,0.25);
    unsigned Rbase  = 22;
    unsigned win = 30;
    __float128 rProb = direct(Rpct, value, Rbase, win);
    cout << (double)rProb << endl;
    return 0;
}

export CILK_NWORKERS=1 && ./code.exe:的样本输出

sumProbe=1

0.101812

export CILK_NWORKERS=4 && ./code.exe:的样本输出

sumProb=0.948159

断言失败:(fabs(1.0-sumProbe)<0.01),函数直接,文件代码.c,第61行。

中止陷阱:6

这是因为竞争条件。cilk_for是并行for算法的实现。如果你想使用并行,你必须使用独立的迭代(独立的数据)。这非常重要。您必须为您的案例使用cilk减速器:https://www.cilkplus.org/tutorial-cilk-plus-reducers

为了澄清,sumProbe上至少有一个种族。每个并行工作者将在该位置进行读取/修改/写入。正如sribin上面提到的,解决这样的问题就是减速器的作用。

完全有可能在你的项目中有不止一场比赛。唯一可以确定的方法是在种族检测器下运行它,因为发现种族是计算机比人类更擅长的事情之一。Cilkscreen种族检测器是一种免费的可能性,可从cilkpls.org网站获得。不幸的是,它不支持gcc/g++。

相关内容

  • 没有找到相关文章

最新更新