2

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

我读过这可能是由于竞争条件造成的,但我不确定代码具体是什么导致了这种情况或如何改善它。此外,我意识到这一点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

总和概率 = 1

0.101812

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

sumProb = 0.948159

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

中止陷阱:6

4

2 回答 2

1

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

于 2016-08-04T06:15:20.510 回答
1

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

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

于 2016-08-05T20:34:18.140 回答