Fortran OpenMP, где будет размещен массив

У меня вопрос о 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 )
  • В первом коде есть две критические области. Я бы предположил, что они замедлили бы выполнение и не очень хорошо масштабировались. (На самом деле я не уверен, могу ли я просто пропустить их, потому что выделение выполняется с сохранением потоков?) Но если массив был выделен в стеке, это должно быть быстрее из-за более быстрого доступа.
  • Во втором коде я уверен, что массив находится в куче, что обеспечивает более медленный доступ. Но если массив в первом коде также размещен в куче, я сохраню критические реакции + это только одно выделение / освобождение. Должно быть быстрее?
  • Не играет ли здесь какой-то роли размер массива?
  • Если бы он был выделен в куче, есть ли способ принудительно выделить его в стеке?

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


person Cabadath    schedule 19.03.2012    source источник
comment
Вы можете сделать localArr => arr..., но это означает, что arr используется совместно между потоками. Я думаю, ты этого не хочешь. Указатель localArr будет иметь копию для каждого потока, но указанное содержимое будет совместно использоваться. Изменения в одном потоке содержимого массива будут отражены в других потоках.   -  person Jason    schedule 07.12.2017


Ответы (2)


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

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

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

allocate( arr(BIGNUMBER) )

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

  arr = 5
  
  print *, arr

!$omp end parallel
deallocate( arr )


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
person Vladimir F    schedule 19.03.2012
comment
Хорошо, спасибо за ваше объяснение. С критиком не был уверен, потому что он синхронный. После критической области следует! $ Omp do, и я не уверен, подразумевает ли начало этого барьер (массивы должны быть выделены до начала цикла do). Думаю, я выбрал спасительный путь. Но само время выделения на самом деле не должно быть такой большой проблемой, но я постараюсь отбросить критическое и посмотреть, что произойдет :) thx. - person Cabadath; 20.03.2012
comment
OpenMP всегда выделяет память в стеке. Единственный способ предотвратить это - вручную выделить ваш массив внутри параллельного блока, как это сделал OP в первом примере. - person Jason; 07.12.2017
comment
@Jason Нет ничего лучше, чем выделяет OpenMP. Распределяет или нет код, сгенерированный компиляторами Фортрана. Что происходит, когда действует OpenMP, выходит за рамки стандартного Фортрана. И вы конечно ошибаетесь. Когда массив становится доступным для размещения, частные копии будут созданы в куче. Да еще когда вы выделили ранее параллельный регион и оставили приватизацию на OpenMP. - person Vladimir F; 21.06.2021
comment
@VladimirF Кто или какой код делает частные копии, когда размещение выполняется до параллельной области? Это скрыто в заявлении !$omp parallel default(shared) private(Arr)? - person Jason; 23.06.2021
comment
@ Джейсон Это так. См. Также это обсуждение forum.openmp.org/viewtopic.php?t=2098, также обсуждаются специальные распределители OpenMP 5. - person Vladimir F; 23.06.2021
comment
Вы имеете в виду следующее утверждение о массивах, размещаемых в куче, или есть еще один: только массивы, которые определены как ALLOCATABLE в подпрограмме! $ OMP, имеют свои ЧАСТНЫЕ копии, помещенные в HEAP. Выделенные массивы, предоставленные в качестве стандартных аргументов, этого не делают, если только они не определены как ALLOCATABLE в подпрограмме omp (не проверены). - person Jason; 26.06.2021
comment
Да, но вся ветка информативна. - person Vladimir F; 26.06.2021

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

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

person Ian Bush    schedule 19.03.2012
comment
Я действительно исходил из предположения, что память в стеке доступна быстрее, чем в куче. Я сейчас путаю это с общим / частным? Доступ к общим массивам медленнее (и я думал, что это означает, что он находится в куче), а доступ к частным массивам быстрый (стек). Вполне возможно, что у меня здесь что-то задом наперед. Также следует добавить, что время выделения не является проблемой, это просто огромный доступ к этому большому массиву, поэтому я хотел бы, чтобы это было как можно быстрее. - person Cabadath; 20.03.2012
comment
@Cabadath С точки зрения доступа к основной памяти не имеет значения, обращаетесь ли вы к стеку или к куче. Это просто область основной памяти, не более того. Аналогично для частного / общего доступа. Медленным является синхронизация, например ложное совместное использование, а не доступ как таковой. - person Vladimir F; 21.06.2021