将多维数组作为一维数组传递的最佳方法

时间:2017-11-06 04:07:15

标签: fortran

我有一个子程序,填充任意长度的1级数组。

subroutine populate_array_1D(array)
    implicit none
    integer, dimension(:), intent(out) :: array
    array(:) = 1
end subroutine populate_array_1D

我现在想要使用重载修改此例程以接受更高维度的数组。

interface populate_array
    module procedure populate_array_1D, populate_array_2D, populate_array_3D
end interface populate_array

我想要做的是将更高维度的子程序引回到1D子程序。

到目前为止我的想法:

  1. 切割数组,然后逐个传递切片:

    subroutine populate_array_2D(array)
        implicit none
        integer, dimension(:,:), intent(out) :: array
        integer :: i
        do i = lbound(array, 2), ubound(array, 2)
            call populate_array_1D(array(:, i))
        end do
    end subroutine populate_array_2D
    
  2. 创建一个新的自动1D数组,然后使用reshape

    subroutine populate_array_3D(array)
        implicit none
        integer, dimension(:,:,:), intent(out) :: array
        integer :: tmp_array(size(array))
        call populate_array_1D(tmp_array)
        array = reshape(tmp_array, shape(array))
    end subroutine populate_array_3D
    
  3. 假设,就像在这个例子中,任何一个版本的结果都没问题,我只担心性能。 (我应该补充一点,我不能只制作一个elemental子程序,因为它不能pure。)

    或者是否有一个更好的版本,我可以将多维数组传递到一个假装它是一维数组的子程序中?

    (最终我想用不同编译器和/或机器上尽可能确定的PRNG替换对RANDOM_NUMBER的调用,假设它们使用相同的种子。)

1 个答案:

答案 0 :(得分:0)

正如francescalus所指出的那样,基本过程可能是不纯正的(从Fortran 2008开始)。

或者,您可以使用Fortran的固有C互操作性 获得对2D阵列的内存位置的低级访问。下面的子例程构建一个指向2D数组的1D指针:

subroutine populate_array_2D(array)
    use iso_c_binding, only: C_F_POINTER, C_LOC

    integer, dimension(:,:), target, contiguous, intent(out) :: array

    integer, dimension(:), pointer :: ptr_1d

    call C_F_POINTER (C_LOC(array), ptr_1d, [size(array)])
    call populate_array_1D(ptr_1d)
end subroutine populate_array_2D

编辑:

c_f_pointer的呼叫可以替换为 指针中的等效绑定重映射列表: ptr_1d(1:size(array)) => array (尽管使用ifort18进行编译会错误地显示warning message,这对于Fortran 2008无效)。