Есть ли способ избежать вложенных циклов do в Fortran 90? - PullRequest
2 голосов
/ 24 марта 2019

Я читаю некоторые скорости для молекул вдоль временной траектории. Я пытаюсь вычислить v_i (t) * v_j (t + n∆t), где i и j не обязательно для одного и того же атома.

Я использую вложенные циклы do для вычислений, которые по определению для разных временных шагов, разных молекул и разных атомов. У меня есть несколько вложенных циклов do, что замедляет код и приводит к проблемам с памятью. Я хочу избежать этих проблем, если это возможно. Как я могу улучшить свой код, используя Fortran 90?

   PROGRAM BUILD

   IMPLICIT NONE
   INTEGER :: I,K,L,L1,L2,M1,M2,T,T1,T2,NCON,NMOL,NSIT,SPLIT,LOOP
   REAL(8) :: X,Y,Z,V1,V2,V3,R,TRASH
   REAL(8),ALLOCATABLE :: VX(:,:,:),VY(:,:,:),VZ(:,:,:)
   REAL(8),ALLOCATABLE :: NORM(:,:,:,:,:),V(:,:,:,:,:)

   ! Input

   NCON = 100001 ! Number of configurations
   NMOL = 524 ! Number of molecules
   NSIT = 6 ! Number of sites on each molecule

   SPLIT = 50 ! Number of subgroups of configurations
   LOOP = (NCON-1)/SPLIT ! Number of configurations in each subgroup

   !       *       *       *       *       *       *       *       *       *

   ! Allocate memory

   ALLOCATE ( VX(0:LOOP,NMOL,NSIT) )
   ALLOCATE ( VY(0:LOOP,NMOL,NSIT) )
   ALLOCATE ( VZ(0:LOOP,NMOL,NSIT) )
   ALLOCATE ( V(0:LOOP,NMOL,NMOL,NSIT,NSIT) )
   ALLOCATE ( NORM(0:LOOP,NMOL,NMOL,NSIT,NSIT) )
   ALLOCATE ( VIVJ(0:LOOP,NSIT,NSIT) )
   ALLOCATE ( N(0:LOOP,NSIT,NSIT) )

   ! Initialize

   VX = 0.0D0
   VY = 0.0D0
   VZ = 0.0D0
   V = 0.0D0
   NORM = 0.0D0
   VIVJ = 0.0D0
   N = 0.0D0

   ! Read trajectories

   OPEN(UNIT=15,FILE='HISTORY',STATUS='UNKNOWN',ACTION='READ')
   DO I = 1,SPLIT
      WRITE(*,*) I,SPLIT
      DO T = 0,LOOP-1
         DO L = 1,NMOL
            DO K = 1,NSIT
               READ(15,*) V1,V2,V3

               VX(T,L,K) = V1
               VY(T,L,K) = V2 
               VZ(T,L,K) = V3

            END DO

         END DO

      END DO

      ! Calculate functions

      DO T1 = 1,LOOP

         DO T2 = T1,LOOP

            DO L1 = 1,NMOL

               DO M1 = 1,NSIT

                  DO L2 = 1,NMOL

                     DO M2 = 1,NSIT

                        ! Includes all atoms, both intermolecular and intramolecular

                        ! Keep all of the molecules
                        V(T2-T1,L1,L2,M1,M2) = V(T2-T1,L1,L2,M1,M2) + & 
                                         VX(T1,L1,M1)*VX(T2,L2,M2) + & 
                                         VY(T1,L1,M1)*VY(T2,L2,M2) + & 
                                         VZ(T1,L1,M1)*VZ(T2,L2,M2)

                        ! Accounting
                        NORM(T2-T1,L1,L2,M1,M2) = NORM(T2-T1,L1,L2,M1,M2) + 1.0D0

                     END DO

                  END DO

               END DO

            END DO

         END DO

      END DO

   CLOSE(15)

   DEALLOCATE(VX)
   DEALLOCATE(VY)
   DEALLOCATE(VZ)
   DEALLOCATE(V)
   DEALLOCATE(NORM)

   END PROGRAM

1 Ответ

2 голосов
/ 24 марта 2019

Fortran хранит свои массивы в другом порядке, чем C и большинство других языков.

do T = ...
    do L = ...
        do K = ...
            array(T, L, K) = ...
        end do
    end do
end do

всегда будет значительно медленнее, чем

do K = ...
    do L = ...
        do T = ...
            array(T, L, K) = ...
        end do
    end do
end do

при прочих равных условиях.

...