OpenMP сокращение больших массивов в Фортране - PullRequest
1 голос
/ 25 мая 2019

Я знаю, что подобные вопросы иногда задавались: Сокращение массива 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?

...