复制数组:循环与数组操作

Copying arrays: loops vs. array operations

我使用 Fortran 已经有很长时间了,但我有一个问题找不到令人满意的答案。 如果我有两个数组并且我想将一个数组复制到另一个数组中:

real,dimension(0:100,0:100) :: array1,array2
...
do i=0,100
   do j=0,100
      array1(i,j) = array2(i,j)
   enddo
enddo

但我也注意到,如果我这样做,效果也很好:

real,dimension(0:100,0:100) :: array1,array2
...
array1 = array2

而且计算时间相差巨大! (第二个要快得多!) 如果我在没有循环的情况下这样做会不会有问题,因为我不知道也许我不是在处理内存引用的内容? 如果我执行另一个数学步骤,它会改变什么吗:

array1 = array2*5

在不同的架构(集群服务器)或不同的编译器(gfortran、ifort)上是否存在问题?

我必须对大量数据执行各种计算步骤,因此计算时间是个问题。

Fortran 非常擅长执行矢量运算。两者

array1 = array2

array1 = array2*5

是有效的操作。 这种表示法允许编译器有效地并行化 (and/or) 优化代码,因为不存在对操作顺序的依赖。

但是,这些构造等同于显式循环,取决于编译器,哪一个会更快。

内存是否会被复制取决于对数组的进一步处理以及编译器是否可以对其进行优化。如果没有性能提升,可以安全地假设数组将被复制。

@Alexander_Vogt 所说的一切,还有:

do i=0,100
    do j=0,100
        array1(i,j) = array2(i,j)
    enddo
enddo

永远比

do j=0,100
    do i=0,100
        array1(i,j) = array2(i,j)
    enddo
enddo

(除非编译器注意到它并重新排序循环。)

在 Fortran 中,第一个参数变化最快。这意味着在第二个循环中,编译器可以将数组的几个元素一举加载到较低级别的缓存中以对其进行操作。

如果您有多维循环,则始终在第一个索引上进行最内层循环,依此类推。 (如果可能的话。)