Результат кода Cilk Plus зависит от количества работников

У меня есть небольшой кусочек кода, который я хотел бы распараллелить при увеличении масштаба. Я использую cilk_for от Cilk 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:

sumProb = 1

0.101812

Пример вывода для export CILK_NWORKERS=4 && ./code.exe:

sumProb = 0,948159

Утверждение не удалось: (fabs (1.0 — sumProb) < 0.01), функция direct, файл code.c, строка 61.

Ловушка отмены: 6

2

Решение

Это из-за состояния гонки. cilk_for — это реализация параллели для алгоритма. Если вы хотите использовать параллель, вы должны использовать независимую итерацию (независимые данные). Это очень важно. Вы должны использовать редукторы для вашего случая: https://www.cilkplus.org/tutorial-cilk-plus-reducers

1

Другие решения

Чтобы уточнить, на sumProb есть хотя бы одна гонка. Каждый из параллельных работников будет выполнять чтение / изменение / запись в этом месте. Как уже упоминалось выше, решение подобных проблем — это то, для чего нужны редукторы.

Вполне возможно, что в вашей программе более одной гонки. Единственный способ убедиться в этом — запустить его под детектором рас, поскольку поиск рас — это одна из вещей, которую используют компьютеры. много лучше, чем люди. Бесплатной возможностью является детектор расы Cilkscreen, доступный на cilkplus.org Веб-сайт. К сожалению, он не поддерживает gcc / g ++.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector