如何使用多个循环优化此Fortran子例程?

回忆

我正在处理的子例程在数组大小变大时效率很低,例如NN = 1000,KK = 200,MM =200。但是,我无法提出优化它的想法。

program main

  implicit none

  integer :: NN, KK, MM
  integer, allocatable, dimension(:,:) :: id
  complex*16, allocatable, dimension(:) :: phase
  complex*16 :: phase_base(3)
  real*8, allocatable, dimension(:,:) :: wave_base

  complex*16, allocatable, dimension(:,:) :: wave
  integer :: i, j, k, n

  NN = 1000
  KK = 200
  MM = 200

  allocate(id(MM,3))
  allocate(phase(KK))
  allocate(wave_base(KK, NN*(NN+1)/2 ))
  allocate(wave(NN, NN))

  id(:,:) = 2

  phase_base(:) = (1.0d0,1.0d0)

  wave_base(:,:) = 1.0d0

  phase(:) = (1.0d0,1.0d0)

  call  noise_wave(NN, KK, MM, id, phase, phase_base, wave_base, wave)

  deallocate(id)
  deallocate(phase)
  deallocate(wave_base)
  deallocate(wave)

end program main

subroutine noise_wave(NN, KK, MM, id, phase_1, phase_base, wave_base, wave)
  implicit none

  integer, intent(in) :: NN, KK, MM
  integer, intent(in), dimension(MM, 3) :: id
  complex*16, intent(in) :: phase_1(KK)
  complex*16, intent(in) :: phase_base(3)
  real*8,  intent(in) :: wave_base(KK, NN*(NN+1)/2 )

  complex*16, intent(out) :: wave(NN, NN)

  integer :: i, j, k, p, n
  integer :: x, y, z
  real :: start, finish
  complex*16 :: phase_2, phase_2_conjg

  do p = 1, MM

    x = id(p, 1)
    y = id(p, 2)
    z = id(p, 3)

    phase_2 = (phase_base(1) ** x) * (phase_base(2) ** y) * (phase_base(3) ** z)

    phase_2_conjg = conjg(phase_2)

    n = 0
    do j = 1, NN
      do i = 1, j   ! upper triangle

        n = n + 1

        do k = 1, KK

          wave(i,j) = wave(i,j) + wave_base(k,n) * phase_1(k) * phase_2_conjg

        enddo

        wave(j,i) = conjg(wave(i,j) )

      enddo
    enddo
  enddo

end subroutin

有人可以给我一些提示吗?(我已经完成了建议的优化。此外,按照Ian的建议,我添加了一个小测试。因此您可以直接对其进行测试。)

回忆

这是我的解决方案,遵循上面的好主意。在使用OpenMP之前,效率仍有提升的空间。例如,子例程中的第一个k循环可以通过求和函数消除。

program main

  implicit none

  integer :: NN, KK, MM
  integer, allocatable, dimension(:,:) :: id
  complex*16, allocatable, dimension(:) :: phase
  complex*16 :: phase_base(3)
  real*8, allocatable, dimension(:,:) :: wave_base

  complex*16, allocatable, dimension(:,:) :: wave
  integer :: i, j, k, n

  NN = 1000
  KK = 200
  MM = 200

  allocate(id(MM,3))
  allocate(phase(KK))
  allocate(wave_base(KK, NN*(NN+1)/2 ))
  allocate(wave(NN, NN))

  id(:,:) = 2

  phase_base(:) = (1.0d0,1.0d0)

  wave_base(:,:) = 1.0d0

  phase(:) = (1.0d0,1.0d0)

  call  noise_wave(NN, KK, MM, id, phase, phase_base, wave_base, wave)

  deallocate(id)
  deallocate(phase)
  deallocate(wave_base)
  deallocate(wave)

end program main

subroutine noise_wave(NN, KK, MM, id, phase_1, phase_base, wave_base, wave)
  implicit none

  integer, intent(in) :: NN, KK, MM
  integer, intent(in), dimension(MM, 3) :: id
  complex*16, intent(in) :: phase_1(KK)
  complex*16, intent(in) :: phase_base(3)
  real*8,     intent(in) :: wave_base(KK, NN*(NN+1)/2 )
  complex*16, intent(out):: wave(NN, NN)

  integer :: i, j, k, p, n
  integer :: x, y, z
  real :: start, finish
  complex*16 :: phase_2, phase_2_conjg
  complex*16 :: wave_tmp(NN*(NN+1)/2)
  complex*16 :: wave_tmp_2(NN*(NN+1)/2)

  do k = 1, KK

    wave_tmp(:) = wave_tmp(:) + wave_base(k,:) * phase_1(k)

  enddo

  do p = 1, MM
    phase_2 = product(phase_base(:)**id(p,:) )
    phase_2_conjg = conjg(phase_2)

    wave_tmp2(:) = wave_tmp2(:) + wave_tmp(n) * phase_2_conjg
  enddo

  n = 0
  do j = 1, NN
    do i = 1, j
        n = n + 1
        wave(i,j) = wave_tmp2(n)
        wave(j,i) = conjg(wave_tmp2(n) )
    enddo
  enddo

end subroutine

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用子例程退出Fortran中的“ do while”循环

来自分类Dev

如何编译Fortran子例程

来自分类Dev

如何使用SymPy编码源生成Fortran子例程

来自分类Dev

如何优化此数组循环

来自分类Dev

如何优化此数组循环

来自分类Dev

如何使用numpy在数组上优化此双循环?

来自分类Dev

如何在C语言中使用fortran模块子例程

来自分类Dev

如何在Fortran子例程中使用可分配数组?

来自分类Dev

如何在C语言中使用fortran模块子例程

来自分类Dev

Fortran 90,如何在子例程中使用派生类型中定义的数组

来自分类Dev

如何使用f2py将字符串数组传递给Fortran子例程

来自分类Dev

“递归”属性如何影响FORTRAN90子例程的性能

来自分类Dev

“递归”属性如何影响FORTRAN90子例程的性能

来自分类Dev

在Fortran 90中的模块内部使用子例程

来自分类Dev

R使用字符参数调用Fortran子例程

来自分类Dev

使用函数或子例程调用的Fortran行继续

来自分类Dev

如何优化此for循环的计算速度?

来自分类Dev

我如何优化此python循环?

来自分类Dev

如何优化此方法并避免foreach循环

来自分类Dev

R调用Fortran子例程

来自分类Dev

Fortran语法(子例程的声明)

来自分类Dev

在并行 Fortran do 循环中调用内部子例程时,子例程无法访问迭代变量的正确值

来自分类Dev

条件 Fortran 循环的优化

来自分类Dev

如何要求文件并使用其子例程

来自分类Dev

如何使用C中的单位编号参数调用Fortran例程

来自分类Dev

fortran:如何将空指针传递给子例程,该子例程将在其中定义并返回

来自分类Dev

如何使用(L,S)apply系列在R中优化此慢速嵌套循环?

来自分类Dev

使用多个for循环优化Python脚本

来自分类Dev

如何将多个参数传递给子例程?

Related 相关文章

  1. 1

    使用子例程退出Fortran中的“ do while”循环

  2. 2

    如何编译Fortran子例程

  3. 3

    如何使用SymPy编码源生成Fortran子例程

  4. 4

    如何优化此数组循环

  5. 5

    如何优化此数组循环

  6. 6

    如何使用numpy在数组上优化此双循环?

  7. 7

    如何在C语言中使用fortran模块子例程

  8. 8

    如何在Fortran子例程中使用可分配数组?

  9. 9

    如何在C语言中使用fortran模块子例程

  10. 10

    Fortran 90,如何在子例程中使用派生类型中定义的数组

  11. 11

    如何使用f2py将字符串数组传递给Fortran子例程

  12. 12

    “递归”属性如何影响FORTRAN90子例程的性能

  13. 13

    “递归”属性如何影响FORTRAN90子例程的性能

  14. 14

    在Fortran 90中的模块内部使用子例程

  15. 15

    R使用字符参数调用Fortran子例程

  16. 16

    使用函数或子例程调用的Fortran行继续

  17. 17

    如何优化此for循环的计算速度?

  18. 18

    我如何优化此python循环?

  19. 19

    如何优化此方法并避免foreach循环

  20. 20

    R调用Fortran子例程

  21. 21

    Fortran语法(子例程的声明)

  22. 22

    在并行 Fortran do 循环中调用内部子例程时,子例程无法访问迭代变量的正确值

  23. 23

    条件 Fortran 循环的优化

  24. 24

    如何要求文件并使用其子例程

  25. 25

    如何使用C中的单位编号参数调用Fortran例程

  26. 26

    fortran:如何将空指针传递给子例程,该子例程将在其中定义并返回

  27. 27

    如何使用(L,S)apply系列在R中优化此慢速嵌套循环?

  28. 28

    使用多个for循环优化Python脚本

  29. 29

    如何将多个参数传递给子例程?

热门标签

归档