我有一小段代码,我希望在我升级时并行化。我一直在使用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
答案 0 :(得分:1)
这是因为竞争条件。 cilk_for是算法并行的实现。如果要使用parallel,则必须使用独立迭代(独立数据)。这非常重要。您必须为您的案例使用cilk reducer:https://www.cilkplus.org/tutorial-cilk-plus-reducers
答案 1 :(得分:1)
澄清一下,sumProb上至少有一场比赛。每个并行工作程序将在该位置执行读取/修改/写入。正如上面提到的sribin,解决这样的问题是减速器的用途。
您的计划中不止一场比赛完全有可能。唯一可以确定的方法是在竞赛检测器下运行它,因为找到比赛是计算机比人类更强更强的事情之一。可以免费使用的是Cilkscreen竞赛探测器,可从the documentation网站获得。不幸的是,它不支持gcc / g ++。