OpenMP распараллеливание вычисления пи либо медленно, либо неправильно - PullRequest
4 голосов
/ 24 января 2012

У меня проблемы с распараллеливанием моего метода Монте-Карло для вычисления числа Пи.Вот параллельный цикл for:

#pragma omp parallel for private(i,x,y) schedule(static) reduction(+:count)
  for (i = 0; i < points; i++) {
    x = rand()/(RAND_MAX+1.0)*2 - 1.0;
    y = rand()/(RAND_MAX+1.0)*2 - 1.0;

    // Check if point lies in circle
    if(x*x + y*y < 1.0) { count++; }
  }

Проблема в том, что он недооценивает pi, если я использую schedule(static), и медленнее, чем последовательная реализация, если я использую schedule(dynamic).Что я делаю неправильно?Я пробовал другие способы исправить это (например: Использование OpenMP для вычисления значения PI ), но он все еще намного медленнее, чем последовательная реализация.

Заранее спасибо

Ответы [ 2 ]

6 голосов
/ 24 января 2012

Если вы используете функцию библиотеки C rand, эта функция не является повторно входящей или поточно-ориентированной.POSIX предоставляет функцию rand_r, но (цитируя документацию по glibc):

POSIX.1 расширяет стандартные функции C, чтобы поддерживать воспроизводимые случайные числа в многопоточных программах.Однако расширение плохо спроектировано и непригодно для серьезной работы.

В частности, начальное число должно быть целым числом без знака, в котором недостаточно битов для хорошего PRNG.Они рекомендуют использовать функции случайных чисел SVID, из которых nrand48_r, вероятно, то, что вы ищете.

В качестве альтернативы, вы можете использовать другую библиотеку.

1 голос
/ 24 января 2012

Одна вещь, которую вы должны учитывать при параллельном выполнении таких действий, это то, что могут быть разные ошибки округления, вызванные различными способами выполнения вычислений.

Пример:

((A+B) + (C+D)), где (A+B) и (C+D) будут вычислены параллельно, может отличаться от последовательного подхода (((A+B) + C) + D).

...