Fortran OpenMP, где будет размещен массив - PullRequest
1 голос
/ 19 марта 2012

У меня есть вопрос о Fortran-OpenMP и размещаемых массивах.Все просто: где будет выделено место?Если у меня будет что-то вроде

!$omp parallel default(shared) private(arr)
!$omp critical
  allocate( arr(BIGNUMBER) )
!$omp end critical

!do calculations with many arr accesses

!$omp critical
  deallocate( arr )
!$omp end critical
!$omp end parallel

, будет ли выделено пространство в стеке или в куче?Если это в куче, есть ли разница между кодом выше и чем-то вроде этого

allocate( arr(BIGNUMBER, nThread) )
!$omp parallel default(shared) private(localArr)
  iThread = omp_get_thread_num()

  localArr => arr(:, iThread)

  !do calculations with many localArr accesses
!$omp end parallel

deallocate( arr )
  • В первом коде есть две критические области.Я предполагаю, что они замедлят выполнение и не очень хорошо масштабируются.(На самом деле я не уверен, смогу ли я просто пропустить их, потому что выделение является поточно-сохраняемым?) Но если массив был размещен в стеке, то он должен быть быстрее из-за более быстрого доступа.
  • Во втором коде я уверен, что массив находится в куче, что замедляет доступ.Но если массив в первом коде также размещен в куче, то я сохраню критические области + это только один метод выделения / удаления.Должно ли быть быстрее?
  • Играет ли размер массива какой-либо бросок в этом?
  • Если бы он был выделен в куче, есть ли способ принудительно распределить его в стеке?

Короткий вопрос в основном: что может показаться оптимальным решением проблемы?

Ответы [ 2 ]

4 голосов
/ 19 марта 2012

Компиляторы Fortran с OpenMP обычно выделяют автоматическую переменную (включая массивы) в стеке. Когда вы делаете явное распределение I, они будут размещаться в куче, но обратите внимание, что стандарт Fortran вообще не говорит о стеке или куче, это зависит от компилятора. В отл. номер 1 Я бы пропустил критические разделы, потому что вы размещаете частные переменные. Что касается размера, иногда возникают переполнения стека из-за слишком больших автоматических массивов, но это, вероятно, не ваш случай. Какой самый быстрый подход, я не знаю.

Эта программа распределяет массивы в куче в моем компиляторе

integer,parameter :: BIGNUMBER = 100000000
real,dimension(:),allocatable :: arr

!$omp parallel default(shared) private(Arr)
allocate( arr(BIGNUMBER) )
  iThread = omp_get_thread_num()

  arr = 5

  print *, arr

deallocate( arr )
!$omp end parallel


end

и этот в стеке (а затем он падает)

integer,parameter :: BIGNUMBER = 100000000
real arr(BIGNUMBER)

!$omp parallel default(shared) private(Arr)
  iThread = omp_get_thread_num()

  arr = 5

  print *, arr

!$omp end parallel


end
2 голосов
/ 19 марта 2012

Хорошо, Владимир говорит, что большинство из того, что я сказал бы (не упомянуто в стандарте, полностью зависит от реализации, почему вы используете критические замечания для защиты своих рядовых?)

Но ... высоздается впечатление, что вы думаете, что доступ к памяти, выделенной в стеке, несколько быстрее, чем в куче.В любой типичной реализации это не так - время доступа одинаково. Распределение памяти в стеке обычно быстрее, чем в куче, но как только оно выделено, время для доступа к нему остается тем же.Поэтому я бы сократил критику и пошел по пути 1 - это проще, держать вещи частными - это хорошо, указатели - плохо, а если время выделения памяти - ваш ограничительный шаг, то вы почти наверняка не получили достаточно работы в параллельной области для параллелизацииэто стоит.

...