Я знаю, что подобные вопросы иногда задавались: Сокращение массива Openmp с Fortran , Сокращение массива в OpenMP , даже на форумах Intel (https://software.intel.com/en-us/forums/intel-moderncode-for-parallel-architectures/topic/345415)но я хотел бы узнать ваше мнение, потому что масштабируемость, которую я получаю, не та, которую я ожидаю.
Поэтому мне нужно заполнить действительно большой массив комплексных чисел, который я хотел бы распараллелить с OpenMP.Наш первый подход такой:
COMPLEX(KIND=DBL), ALLOCATABLE :: huge_array(:)
COMPLEX(KIND=DBL), ALLOCATABLE :: thread_huge_array(:)
INTEGER :: huge_number, index1, index2, index3, index4, index5, bignumber1, bignumber2, smallnumber, depending_index
ALLOCATE(huge_array(huge_number))
!$OMP PARALLEL FIRSTPRIVATE(thread_huge_array)
ALLOCATE(thread_huge_array(SIZE(huge_array)))
thread_huge_array = ZERO
!$OMP DO
DO index1=1,bignumber1
! Some calculations
DO index2=1,bignumber2
! Some calculations
DO index3=1,6
DO index4=1,6
DO index5=1,smallnumber
depending_index = function(index1, index2, index3, index4, index5)
thread_huge_array(depending_index) = thread_huge_array(depending_index)
ENDDO
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END DO
!$OMP BARRIER
!$OMP MASTER
huge_array = ZERO
!$OMP END MASTER
!$OMP CRITICAL
huge_array = huge_array + thread_huge_array
!$OMP END CRITICAL
DEALLOCATE(thread_huge_array)
!$OMP END PARALLEL
Итак, с этим подходом мы получаем хорошую масштабируемость до 8 ядер, разумную масштабируемость до 32 ядер и от 40 ядер, это медленнее, чем с 16 ядрами (у нас естьмашина с 80 физическими ядрами.) Конечно, мы не можем использовать предложение REDUCTION, потому что размер массива настолько велик, что он не помещается в стек (даже увеличивая ulimit до максимально допустимого в машине).
Мы попробовали другой подход с этим:
COMPLEX(KIND=DBL), ALLOCATABLE :: huge_array(:)
COMPLEX(KIND=DBL), POINTER:: thread_huge_array(:)
INTEGER :: huge_number
ALLOCATE(huge_array(huge_number))
ALLOCATE(thread_huge_array(SIZE(huge_array),omp_get_max_threads()))
thread_huge_array = ZERO
!$OMP PARALLEL PRIVATE (num_thread)
num_thread = omp_get_thread_num()+1
!$OMP DO
DO index1=1,bignumber1
! Some calculations
DO index2=1,bignumber2
! Some calculations
DO index3=1,6
DO index4=1,num_weights_sp
DO index5=1,smallnumber
depending_index = function(index1, index2, index3, index4, index5)
thread_huge_array(depending_index, omp_get_thread_num()) = thread_huge_array(depending_index, omp_get_thread_num())
ENDDO
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END DO
!$OMP END PARALLEL
huge_array = ZERO
DO index_ii = 1,omp_get_max_threads()
huge_array = huge_array + thread_huge_array(:,index_ii)
ENDDO
DEALLOCATE(thread_huge_array)
DEALLOCATE(huge_array)
И в этом последнем случае мы получаем более длинные времена для метода (из-зарасположение памяти, которое намного больше) и хуже относительного ускорения.
Можете ли вы дать несколько советов для достижения лучшего ускорения?Или это невозможно с этими огромными массивами с OpenMP?