Próbuję pisać (aktualizować) w tablicy podwójnej w sposób równoległy za pomocą OpenMP. Chodzi o to, że element, który wymaga aktualizacji, może być aktualizowany więcej niż jeden raz, a sam element jest obliczany w locie. To czyni go bardzo podatnym na warunki wyścigowe, chyba że "zablokuję" obszar pamięci odpowiadający elementowi, który jest aktualizowany operacją atomową. W poniższym przykładzie:Aktualizowanie tablicy dublu z operacjami atomowymi
#include<omp.h>
#include<stdlib.h>
int main()
{
double *x=NULL, contribution = 1234.5;
size_t xlen=1000, i, n;
if ((x = (double *) calloc(xlen,sizeof(double))) == NULL) exit(-1)
#pragma omp parallel for shared(x) private(n,contribution)
for (i=0; i<xlen; i++) {
n = find_n_on_the_fly(i);
#pragma omp atomic update
x[n]+=contribution; // in the more complicated case contributions are different
}
return 0;
}
Z takim podejściem wciąż jestem w wyścigu. Próbowałem używać krytycznych sekcji, ale całkowicie mnie to zabija, ponieważ tablice są duże, a liczba aktualizacji jest również duża.
Pytanie: co jest nie tak z tym podejściem? Czy istnieje lepszy sposób radzenia sobie z tym?
Uwaga: Aby sobie z tym poradzić, robię coś głupiego, tworząc kopie tablic dla każdego wątku i zmniejszając je później. Ale ograniczenia pamięci nie pozwalają mi iść dalej.
dlaczego nie utworzyć listę par "n"/"wkład" i kontynuować wciskanie w nią, a następnie zredukować je do tablicy "x" lub innego rodzaju rzadkiej reprezentacji? – user3528438
@ user3528438 To jest pomysł i jest zgodny z moją notatką. Czy masz rzeczywisty przykład pracy, który nie ogranicza się do tego, co już robię? –
Z definicji operacja atomowa dla wartości 64-bitowej jest możliwa tylko w 64-bitowej (lub większej) architekturze sprzętowej. Biblioteka zmiennoprzecinkowa może znajdować się w katalogu głównym problemu, który tu widzisz. Czy próbowałeś typowania w "unsigned long long"? Ponadto tablica asocjacyjna byłaby dużo szybsza do wyszukiwania elementów tablicy, niż do przeszukiwania pętli dla każdego elementu. –