zaokrąglenia w dodawaniu (wielowątkowość)

0

Cześć, piszę do was z takim oto zapytaniem:
czy mogą powstać różnice gdy zamiast takiego kodu:

    double sum = 0.0;
    for(int i = 0; i < 40; i++)
        sum += var[i];    //var to jakaś zmienna

rozbijemy to na 4 niezależne sumy tj. np. tak:

    double sum = 0.0;
    double sumt[4]{};

    for(int t = 0; t < 4; t++)
        {
        for(int i = t; i < 40; i = i + 4)
            sumt[t] += var[i];
        }
    for(int t = 0; t < 4; t++)
        sum += sumt[t];

Pytam, gdyż napisałem sobie programik (sieć neuronową), która wykonuje proste operacje -> głównie mnoży i dodaje. Po przeprowadzeniu prostych testów i dojściu do wniosku, że chyba wszystko działa prawidłowo postanowiłem zmienić funkcję uczącą tak, by wykorzystała 4 wątki w celu przyśpieszenia wykonywania kodu. W związku z powyższym każdy wątek miał swoją tablicę do której sumowałem pewne rzeczy a następnie je dodawałem.
Problem polega jednak na tym, że powstają minimalne różnice i zastanawiam się co jest tego przyczyną? Różnice są śmiesznie małe, ale jednak wolałbym je wyeliminować :(...
Z góry dzięki za waszą pomoc!
Aha, i kod jest tak wykonany, że nie używam żadnych mutex-ów etc. Każdy wątek ma swoją tablicę, do której zapisuje wszystkie istotne informacje a później, po wykonaniu wszystkich obliczeń główny wątek sumuje obliczenia.

1

Są błędy zaokrągleń, więc liczby zmiennoprzecinkowe zsumowane w innej kolejności dają inny wynik.

0
_13th_Dragon napisał(a):

Są błędy zaokrągleń, więc liczby zmiennoprzecinkowe zsumowane w innej kolejności dają inny wynik.

Dzięki @_13th_Dragon. A możesz wyjaśnić, dlaczego kolejność dodawania ma jakiekolwiek znaczenie? O_o

3

Każde (potencjalnie) dodawanie liczb zmiennoprzecinkowych jest obarczone pewnym błędem. Błąd ten kumuluje się, i po wielu dodawaniach otrzymujesz ten drobny błąd w wyniku.
Sposobów na walczenie z błędem zaokrąglenia jest trzy dużo, na przykład (w kolejności od najprostszych do najtrudniejszch):

  • użycie liczb o większej precyzji (double zamiast float) (mniejszy błąd zaokrąglenia)
    • alternatywa powyższego - użycie liczb stałoprzecinkowych (GCC ma do tego rozszerzenie, można też symulować na intach) (brak błędu zaokrąglenia)
  • posortowanie liczb rosnąco przed dodawaniem (mniejszy błąd zaokrąglenia)
  • http://en.wikipedia.org/wiki/Kahan_summation_algorithm

1 użytkowników online, w tym zalogowanych: 0, gości: 1