Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays Fortran中大型阵列的OpenMP简化_Arrays_Fortran_Openmp_Fortran90_Reduction - Fatal编程技术网

Arrays Fortran中大型阵列的OpenMP简化

Arrays Fortran中大型阵列的OpenMP简化,arrays,fortran,openmp,fortran90,reduction,Arrays,Fortran,Openmp,Fortran90,Reduction,我知道有时会有人问类似的问题:,甚至在英特尔论坛()中也是如此,但我想知道你的看法,因为我得到的可扩展性不是我所期望的 所以我需要填充一个非常大的复数数组,我想用OpenMP并行化。我们的第一种方法是: COMPLEX(KIND=DBL), ALLOCATABLE :: huge_array(:) COMPLEX(KIND=DBL), ALLOCATABLE :: thread_huge_array(:) INTEGER :: huge_number, index1, index2, index

我知道有时会有人问类似的问题:,甚至在英特尔论坛()中也是如此,但我想知道你的看法,因为我得到的可扩展性不是我所期望的

所以我需要填充一个非常大的复数数组,我想用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
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)
因此,通过这种方法,我们可以在8个核之前获得良好的可扩展性,在32个核之前获得合理的可扩展性,而在40个核之前,它比16个核的速度要慢(我们的机器有80个物理核)。当然,我们不能使用reduce子句,因为数组的大小太大,无法放入堆栈中(甚至将ulimit增加到机器允许的最大值)

我们尝试了一种不同的方法:

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
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的这些大型阵列是不可能的

请展示一些实际的计时和硬件(什么类型的80核?在什么类型的CPU插槽中?)。有多少个NUMA节点?并不是说代码不可编译,所以我们不能自己做任何测试。请注意,上面的第一种形式有一个bug,因为master不是一个工作共享结构,因此在最后没有一个隐式障碍。另一方面,do是一,所以在它之后不需要屏障,因为构造的末尾自动提供了一个屏障。同样在第二种情况下,为什么不并行最后的加法呢?这与thread_huger_ArrayFladimir的第一个索引非常相似,我使用的机器有80个CPU,每个套接字20个内核和4个NUMA节点。另外,实际情况和不同线程的计时是:1线程132.90 8线程17.58(0.42)| 19.22(0.37)20线程8.33(0.951)| 9.522(0.785)40线程5.89(1.802)| 7.79(1.58)80线程6.748(3.597)| 10.188(3.27)。第一个结果是第一个代码,第二个结果是串行缩减。您可以看到,缩减所花费的时间太长,加速效果更差。在第二个版本中,不使用数组语法,只需在大型数组的元素上写一个循环,然后添加线程版本。这个循环中巨大的_数组的每个元素都是独立的,因此可以并行。此外,您不必在巨大的_数组上循环两次,一次将其归零,一次添加。你可以在这个循环中完成这一切。请展示一些实际的计时和硬件(什么样的80核?在什么样的CPU插槽中?)。有多少个NUMA节点?并不是说代码不可编译,所以我们不能自己做任何测试。请注意,上面的第一种形式有一个bug,因为master不是一个工作共享结构,因此在最后没有一个隐式障碍。另一方面,do是一,所以在它之后不需要屏障,因为构造的末尾自动提供了一个屏障。同样在第二种情况下,为什么不并行最后的加法呢?这与thread_huger_ArrayFladimir的第一个索引非常相似,我使用的机器有80个CPU,每个套接字20个内核和4个NUMA节点。另外,实际情况和不同线程的计时是:1线程132.90 8线程17.58(0.42)| 19.22(0.37)20线程8.33(0.951)| 9.522(0.785)40线程5.89(1.802)| 7.79(1.58)80线程6.748(3.597)| 10.188(3.27)。第一个结果是第一个代码,第二个结果是串行缩减。您可以看到,缩减所花费的时间太长,加速效果更差。在第二个版本中,不使用数组语法,只需在大型数组的元素上写一个循环,然后添加线程版本。这个循环中巨大的_数组的每个元素都是独立的,因此可以并行。此外,您不必在巨大的_数组上循环两次,一次将其归零,一次添加。你可以在这个循环中完成这一切。