Как правильно передать число lambdaeff ядрам, используя OpenMP в этом коде на Фортране? - PullRequest
0 голосов
/ 03 февраля 2020

Я пытаюсь распараллелить код, который вычисляет два целых числа nue и nut; эти числа затем используются для вычисления другого числа lambdaeff. Я могу показать (глупо) MWE (фактический код - 1200 строк кода Монте-Карло):

Do n=1, 100
 nue=int(100*rand())
 nut=int(50*rand())
 lambdaeff=lambdaeff+(nue-nut)^2
end do

Если я распараллеливаю код, как указано здесь , используя параллель do l oop, я не уверен, что число lambdaeff будет правильно передано различным ядрам. Как я могу изменить последнюю строку l oop для правильной передачи lambdaeff ядрам?

1 Ответ

0 голосов
/ 05 февраля 2020

Чтобы суммировать комментарии @Vadimir F, @PetrH и @Ian Bu sh:

  • НЕ используйте rand(), так как он не безопасен для потоков; используйте random_number() вместо
  • Вы хотите использовать OpenMP reduction,
  • Существует большая разница между ядром и нить , пожалуйста, посмотрите (последний термин применяется здесь).

РЕДАКТИРОВАТЬ:

Если у меня была вторая переменная lnet=lnet-nue+nut, которая должна использоваться всеми потоками, такими как lambdaeff, как мне изменить оператор сокращения?

program main
  use, intrinsic :: omp_lib
  implicit none
  integer :: i, tid, nthreads
  integer :: nue, nut, lambdaeff = 0, lnet = 0
  real    :: r(2)

  ! Set number of threads
  nthreads = OMP_get_max_threads()
  write (*,*) "Using ", nthreads, "thread(s)"

  !$OMP PARALLEL NUM_THREADS(nthreads) PRIVATE(tid)
  ! Who am I?
  tid = OMP_get_thread_num()

  ! Reduction do loop
  !$OMP DO REDUCTION(+:lambdaeff,lnet) PRIVATE(nue,nut,r)
  do i = 1, 100
    call random_number(r)
    nue = int(100*r(1))
    nut = int(50*r(2))
    lambdaeff = lambdaeff + (nue-nut)**2
    lnet = lnet+(nue-nut)

  end do
  !$OMP END DO

  ! lambdaeff is same for all threads
  write (*,*) tid, lambdaeff, lnet

  !$OMP END PARALLEL

end program main
...