Cilk Plus代码结果取决于工人数量

时间:2016-08-04 05:26:01

标签: c++ multithreading 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的示例输出:

  

sumProb = 1

     

0.101812

export CILK_NWORKERS=4 && ./code.exe的示例输出:

  

sumProb = 0.948159

     

断言失败:(fabs(1.0 - sumProb)&lt; 0.01),函数直接,文件code.c,第61行。

     

中止陷阱:6

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

澄清一下,sumProb上至少有一场比赛。每个并行工作程序将在该位置执行读取/修改/写入。正如上面提到的sribin,解决这样的问题是减速器的用途。

您的计划中不止一场比赛完全有可能。唯一可以确定的方法是在竞赛检测器下运行它,因为找到比赛是计算机比人类更强更强的事情之一。可以免费使用的是Cilkscreen竞赛探测器,可从the documentation网站获得。不幸的是,它不支持gcc / g ++。