три вложенных цикла do при распараллеливании не дают таких же результатов, как последовательный код - PullRequest
1 голос
/ 28 мая 2019

Мне нужно распараллелить этот кусок кода (fortran77) с openmp 4.5.

      DO 700 K=1,KMM1
          K1 = KB1(K)
          K2 = KB2(K)
          DO 700 J=2,JM
              JSB= JSBLK(J)
              J1 = JB1(J)
              J2 = JB2(J)
              DO 700 I=1,IMM1
                  I1 = IB1(I)
                  I2 = IB2(I)
                  DELTA = STORE(I,J,K)
                  B1CHG(I1,J1,K1) = B1CHG(I1,J1,K1) + DELTA
                  B2CHG(I2,J2,K2) = B2CHG(I2,J2,K2) + DELTA
                  SBCHG(JSB)      = SBCHG(JSB)      + DELTA
  700 CONTINUE

Я использовал простое утверждение! OMP PARALLEL DO,! OMP END PARALLEL DO до и после кода и проверенного результата, но они не совпадают. Я инициализировал векторы KB1, KB2, JSBLK, JB1, JB2, IB1, IB2, STORE, B1CHG, B2CHG, SBCHG со случайными значениями и в параллельном цикле я использую другое имя для переменных (например, STOREP вместо STORE ), затем я проверяю, STOREP == STORE, B1CHGP == B2CHG и т. д. Если я удаляю прагму openmp, результаты совпадают. Вот код, который я использую для сравнения и тестирования последовательной и параллельной версии:


     PARAMETER(KMM1=10, JM=5 , IMM1=5  )

     COMMON/VEC/ KB1(KMM1),KB2(KMM1),JSBLK(JM),JB1(JM),JB2(JM),
    &            IB1(IMM1),IB2(IMM1),STORE(IMM1,JM,KMM1),
    &            B1CHG(IMM1,JM,KMM1),B2CHG(IMM1,JM,KMM1),SBCHG(JM)

     COMMON/PARVEC/  STOREP(IMM1,JM,KMM1),
    &            B1CHGP(IMM1,JM,KMM1),B2CHGP(IMM1,JM,KMM1),SBCHGP(JM)




     include 'omp_lib.h'




C---------------------------------------------------------------------     
C   INITIALIZING DUMMY ARRAYS
C RANDOM_NUMBER E' UNA SUBROUTINE DEL FORTRAN 95      
     CALL RANDOM_SEED()
     DO 701 K=1,KMM1

         CALL RANDOM_NUMBER(U)
         KB1(K)=FLOOR((KMM1+1)*U)

         CALL RANDOM_NUMBER(U)
         JH = 0 + FLOOR((KMM1+1)*u)
         KB2(K)=JH

         DO 701 J=2,JM

         CALL RANDOM_NUMBER(U)
         JH = 0 + FLOOR((JM+1)*u)
         JSBLK(J)=JH

         CALL RANDOM_NUMBER(U)
         JH =  0 + FLOOR((JM+1)*U)
         JB1(J)=JH

         CALL RANDOM_NUMBER(U)
         JH = 0 + FLOOR((JM+1)*U)
         JB2(J)= JH

         DO 701 I=1,IMM1

             CALL RANDOM_NUMBER(U)
             JH = 0 + FLOOR((IMM1+1)*U)
             IB1(I)=JH


             CALL RANDOM_NUMBER(U)
             JH = 0 + FLOOR((IMM1+1)*U)
             IB2(I)=JH

             CALL RANDOM_NUMBER(STORE(I,J,K))
             CALL RANDOM_NUMBER(B1CHG(I,J,K))
             CALL RANDOM_NUMBER(B2CHG(I,J,K))
             CALL RANDOM_NUMBER(SBCHG(J))

             STOREP(I,J,K) = STORE(I,J,K)
             B1CHGP(I,J,K) = B1CHG(I,J,K)
             B2CHGP(I,J,K) = B2CHG(I,J,K)
             SBCHGP(J)= SBCHG(J)

 701 CONTINUE

C---------------------------------------------------------------------
C PLOTTING THE INITIALIZED ARRAYS FOR VISUAL INSPECTION
     DO 702 K=1,KMM1
         WRITE(6,*) KB1(K),KB2(K) 
         DO 702 J=2,JM
             WRITE(6,*) JSBLK(J),JB1(J),JB2(J)
             DO 702 I=1,IMM1
                 WRITE(6,*) IB1(I),IB2(I),STORE(I,J,K)
                 WRITE(6,*) B1CHG(I,J,K)
                 WRITE(6,*) B2CHG(I,J,K)
                 WRITE(6,*) SBCHG(J)
 702 CONTINUE
C
C
C   NOW THE SERIAL/PARALLEL CODE COMPARING
C
c---------------------------------------------------------------------
C    ENTERING SERIAL REGION    



     SEC1 = omp_get_wtime ( )

     DO 700 K=1,KMM1
         K1 = KB1(K)
         K2 = KB2(K)
         DO 700 J=2,JM
             JSB= JSBLK(J)
             J1 = JB1(J)
             J2 = JB2(J)
             DO 700 I=1,IMM1
                I1 = IB1(I)
                I2 = IB2(I)
                DELTA = STORE(I,J,K)
                B1CHG(I1,J1,K1) = B1CHG(I1,J1,K1) + DELTA
                B2CHG(I2,J2,K2) = B2CHG(I2,J2,K2) + DELTA
                SBCHG(JSB)      = SBCHG(JSB)      + DELTA
 700 CONTINUE

     SEC = omp_get_wtime ( ) - SEC1
     WRITE(6,*) '#CPU SERIAL=', SEC, 'SECONDS.'

C---------------------------------------------------------------------
C     LEAVING SERIAL REGION


C---------------------------------------------------------------------
C    ENTERING PARALLEL REGION

     SEC1 = omp_get_wtime ( )

!$OMP PARALLEL DO

     DO K=1,KMM1
         K1 = KB1(K)
         K2 = KB2(K)
         DO J=2,JM
         JSB= JSBLK(J)
         J1 = JB1(J)
         J2 = JB2(J)

         DO I=1,IMM1
             I1 = IB1(I)
             I2 = IB2(I)
             DELTAP = STOREP(I,J,K)
             B1CHGP(I1,J1,K1) = B1CHGP(I1,J1,K1) + DELTAP
             B2CHGP(I2,J2,K2) = B2CHGP(I2,J2,K2) + DELTAP
             SBCHGP(JSB)      = SBCHGP(JSB)      + DELTAP
     END DO

     END DO
     END DO

!$OMP END PARALLEL DO

     SEC = omp_get_wtime ( ) - SEC1
     WRITE(6,*) '#CPU PARALLEL=', SEC, 'SECONDS.'


C---------------------------------------------------------------------
C     LEAVING PARALLEL REGION



C----------------------------------------------------------------------
C VERIFYING DATA CORRECTNESS 




     DO K=1,KMM1

         DO J=2,JM

             DO I=1,IMM1

                 IF(B1CHG(I,J,K).NE.B1CHGP(I,J,K)) THEN 
                    T=B1CHG(I,J,K)-B1CHGP(I,J,K)
                    WRITE(6,*) 'ERROR  ', T
                 END IF
                 IF(B2CHG(I,J,K).NE.B2CHGP(I,J,K)) THEN
                     WRITE(6,*) 'ERROR' 
                 END IF
                 IF(SBCHG(J).NE.SBCHGP(J)) THEN 
                     WRITE(6,*) 'ERROR'      
                 END IF
     END DO
     END DO
     END DO

     RETURN
     END
...