Ich habe ein kleines Stück Code, den ich parallelisieren möchte, wie ich upscale. Ich habe cilk_for
von Cilk Plus verwendet, um das Multithreading auszuführen. Das Problem ist, dass ich je nach Anzahl der Arbeiter ein anderes Ergebnis bekomme.Cilk Plus Code Ergebnis hängt von der Anzahl der Arbeiter
Ich habe gelesen, dass dies auf eine Race-Bedingung zurückzuführen sein könnte, aber ich bin mir nicht sicher, was speziell über den Code verursacht oder wie es zu verbessern. Außerdem stelle ich fest, dass long
und __float128
Overkill für dieses Problem sind, aber möglicherweise in der Upscaling notwendig sind.
Code:
#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;
}
Beispielausgabe für export CILK_NWORKERS=1 && ./code.exe
:
sumProb = 1
0,101812
Beispielausgabe für export CILK_NWORKERS=4 && ./code.exe
:
sumProb = 0,948159
Assertion fehlgeschlagen: (Fabs (1,0 - sumProb) < 0,01), Funktion direkt, Datei code.c, Zeile 61.
Abort trap: 6
Definition von 'sumProb' und' rProb' als 'cilk :: reducer>' hat den Trick gemacht. Ich verstehe, dass der gleichzeitige Zugriff, das Bearbeiten und Speichern dieser Variablen zu fehlerhaften Ergebnissen führen kann. Ich würde mir vorstellen, dass, wenn ich sie stattdessen in einem Vektor speichern würde und dann summieren würde, würde der Vektor außerhalb der For-Schleife auch funktionieren. –
Stershic