Fortran并行计算的一些例子

以下例子来自https://computing.llnl.gov/tutorials/openMP/exercise.html网站

一、打印线程(Hello world)

C******************************************************************************
C FILE: omp_hello.f
C DESCRIPTION:
C   OpenMP Example - Hello World - Fortran Version
C   In this simple example, the master thread forks a parallel region.
C   All threads in the team obtain their unique thread number and print it.
C   The master thread only prints the total number of threads.  Two OpenMP
C   library routines are used to obtain the number of threads and each
C   thread's number.
C AUTHOR: Blaise Barney  5/99
C LAST REVISED: 
C******************************************************************************

      PROGRAM HELLO
     
      INTEGER NTHREADS, TID, OMP_GET_NUM_THREADS, OMP_GET_THREAD_NUM
  
C     Fork a team of threads giving them their own copies of variables
!$OMP PARALLEL PRIVATE(NTHREADS, TID)


C     Obtain thread number
      TID = OMP_GET_THREAD_NUM()
      PRINT *, 'Hello World from thread = ', TID

C     Only master thread does this
      IF (TID .EQ. 0) THEN
        NTHREADS = OMP_GET_NUM_THREADS()
        PRINT *, 'Number of threads = ', NTHREADS
      END IF

C     All threads join master thread and disband
!$OMP END PARALLEL

      END

 二、循环(Loop work-sharing)

 1 C******************************************************************************
 2 C FILE: omp_workshare1.f
 3 C DESCRIPTION:
 4 C   OpenMP Example - Loop Work-sharing - Fortran Version
 5 C   In this example, the iterations of a loop are scheduled dynamically
 6 C   across the team of threads.  A thread will perform CHUNK iterations
 7 C   at a time before being scheduled for the next CHUNK of work.
 8 C AUTHOR: Blaise Barney  5/99
 9 C LAST REVISED: 01/09/04
10 C******************************************************************************
11  
12       PROGRAM WORKSHARE1
13 
14       INTEGER NTHREADS, TID, OMP_GET_NUM_THREADS,
15      +  OMP_GET_THREAD_NUM, N, CHUNKSIZE, CHUNK, I
16       PARAMETER (N=100)
17       PARAMETER (CHUNKSIZE=10) 
18       REAL A(N), B(N), C(N)
19 
20 !     Some initializations
21       DO I = 1, N
22         A(I) = I * 1.0
23         B(I) = A(I)
24       ENDDO
25       CHUNK = CHUNKSIZE
26 
27 !$OMP PARALLEL SHARED(A,B,C,NTHREADS,CHUNK) PRIVATE(I,TID)
28 
29       TID = OMP_GET_THREAD_NUM()
30       IF (TID .EQ. 0) THEN
31         NTHREADS = OMP_GET_NUM_THREADS()
32         PRINT *, 'Number of threads =', NTHREADS
33       END IF
34       PRINT *, 'Thread',TID,' starting...'
35 !$OMP DO SCHEDULE(DYNAMIC,CHUNK)
36       DO I = 1, N
37         C(I) = A(I) + B(I)
38         WRITE(*,100) TID,I,C(I)
39  100    FORMAT(' Thread',I2,': C(',I3,')=',F8.2)
40       ENDDO
41 !$OMP END DO NOWAIT
42       PRINT *, 'Thread',TID,' done.'
43 !$OMP END PARALLEL
44 
45       END

三、Sections work-sharing

C******************************************************************************
C FILE: omp_workshare2.f
C DESCRIPTION:
C   OpenMP Example - Sections Work-sharing - Fortran Version
C   In this example, the OpenMP SECTION directive is used to assign
C   different array operations to each thread that executes a SECTION. 
C AUTHOR: Blaise Barney  5/99
C LAST REVISED: 07/16/07
C******************************************************************************

      PROGRAM WORKSHARE2

      INTEGER N, I, NTHREADS, TID, OMP_GET_NUM_THREADS, 
     +        OMP_GET_THREAD_NUM
      PARAMETER (N=50)
      REAL A(N), B(N), C(N), D(N)

!     Some initializations
      DO I = 1, N
        A(I) = I * 1.5
        B(I) = I + 22.35
        C(N) = 0.0
        D(N) = 0.0
      ENDDO

!$OMP PARALLEL SHARED(A,B,C,D,NTHREADS), PRIVATE(I,TID)
      TID = OMP_GET_THREAD_NUM()
      IF (TID .EQ. 0) THEN
        NTHREADS = OMP_GET_NUM_THREADS()
        PRINT *, 'Number of threads =', NTHREADS
      END IF
      PRINT *, 'Thread',TID,' starting...'

!$OMP SECTIONS

!$OMP SECTION
      PRINT *, 'Thread',TID,' doing section 1'
      DO I = 1, N
         C(I) = A(I) + B(I)
         WRITE(*,100) TID,I,C(I)
 100     FORMAT(' Thread',I2,': C(',I2,')=',F8.2)
      ENDDO

!$OMP SECTION
      PRINT *, 'Thread',TID,' doing section 2'
      DO I = 1, N
         D(I) = A(I) * B(I)
         WRITE(*,100) TID,I,D(I)
      ENDDO


!$OMP END SECTIONS NOWAIT

      PRINT *, 'Thread',TID,' done.'

!$OMP END PARALLEL

      END

四、Combined parallel loop reduction

C******************************************************************************
C FILE: omp_reduction.f
C DESCRIPTION:
C   OpenMP Example - Combined Parallel Loop Reduction - Fortran Version
C   This example demonstrates a sum reduction within a combined parallel loop
C   construct.  Notice that default data element scoping is assumed - there
C   are no clauses specifying shared or private variables.  OpenMP will
C   automatically make loop index variables private within team threads, and
C   global variables shared.
C AUTHOR: Blaise Barney  5/99
C LAST REVISED:
C******************************************************************************

      PROGRAM REDUCTION

      INTEGER I, N
      REAL A(100), B(100), SUM

!     Some initializations
      N = 100
      DO I = 1, N
        A(I) = I *1.0
        B(I) = A(I)
      ENDDO
      SUM = 0.0

!$OMP PARALLEL DO REDUCTION(+:SUM)
      DO I = 1, N
        SUM = SUM + (A(I) * B(I))
      ENDDO

      PRINT *, '   Sum = ', SUM
      END

五、Orphaned parallel loop reduction

C******************************************************************************
C FILE: omp_orphan.f
C DESCRIPTION:
C   OpenMP Example - Parallel region with an orphaned directive - Fortran 
C   Version
C   This example demonstrates a dot product being performed by an orphaned
C   loop reduction construct.  Scoping of the reduction variable is critical.
C AUTHOR: Blaise Barney  5/99
C LAST REVISED:
C******************************************************************************

      PROGRAM ORPHAN
      COMMON /DOTDATA/ A, B, SUM
      INTEGER I, VECLEN
      PARAMETER (VECLEN = 100)
      REAL*8 A(VECLEN), B(VECLEN), SUM

      DO I=1, VECLEN
         A(I) = 1.0 * I
         B(I) = A(I)
      ENDDO
      SUM = 0.0
!$OMP PARALLEL
      CALL DOTPROD
!$OMP END PARALLEL
      WRITE(*,*) "Sum = ", SUM
      END



      SUBROUTINE DOTPROD
      COMMON /DOTDATA/ A, B, SUM
      INTEGER I, TID, OMP_GET_THREAD_NUM, VECLEN
      PARAMETER (VECLEN = 100)
      REAL*8 A(VECLEN), B(VECLEN), SUM

      TID = OMP_GET_THREAD_NUM()
!$OMP DO REDUCTION(+:SUM)
      DO I=1, VECLEN
         SUM = SUM + (A(I)*B(I))
         PRINT *, '  TID= ',TID,'I= ',I
      ENDDO
      RETURN
      END

六、Matrix multiply

C******************************************************************************
C FILE: omp_mm.f
C DESCRIPTION:  
C   OpenMp Example - Matrix Multiply - Fortran Version 
C   Demonstrates a matrix multiply using OpenMP. Threads share row iterations
C   according to a predefined chunk size.
C AUTHOR: Blaise Barney
C LAST REVISED: 1/5/04 Blaise Barney
C******************************************************************************

      PROGRAM MATMULT

      INTEGER  NRA, NCA, NCB, TID, NTHREADS, I, J, K, CHUNK,
     +         OMP_GET_NUM_THREADS, OMP_GET_THREAD_NUM
C     number of rows in matrix A 
      PARAMETER (NRA=62)
C     number of columns in matrix A
      PARAMETER (NCA=15)
C     number of columns in matrix B
      PARAMETER (NCB=7)

      REAL*8 A(NRA,NCA), B(NCA,NCB), C(NRA,NCB)

C     Set loop iteration chunk size 
      CHUNK = 10

C     Spawn a parallel region explicitly scoping all variables
!$OMP PARALLEL SHARED(A,B,C,NTHREADS,CHUNK) PRIVATE(TID,I,J,K)
      TID = OMP_GET_THREAD_NUM()
      IF (TID .EQ. 0) THEN
        NTHREADS = OMP_GET_NUM_THREADS()
        PRINT *, 'Starting matrix multiple example with', NTHREADS,
     +           'threads'
        PRINT *, 'Initializing matrices'
      END IF

C     Initialize matrices
!$OMP DO SCHEDULE(STATIC, CHUNK)
      DO 30 I=1, NRA
        DO 30 J=1, NCA
          A(I,J) = (I-1)+(J-1)
  30  CONTINUE
!$OMP DO SCHEDULE(STATIC, CHUNK)
      DO 40 I=1, NCA
        DO 40 J=1, NCB
          B(I,J) = (I-1)*(J-1)
  40  CONTINUE
!$OMP DO SCHEDULE(STATIC, CHUNK)
      DO 50 I=1, NRA
        DO 50 J=1, NCB
          C(I,J) = 0
  50  CONTINUE

C     Do matrix multiply sharing iterations on outer loop
C     Display who does which iterations for demonstration purposes
      PRINT *, 'Thread', TID, 'starting matrix multiply...'
!$OMP DO SCHEDULE(STATIC, CHUNK)
      DO 60 I=1, NRA
      PRINT *, 'Thread', TID, 'did row', I
        DO 60 J=1, NCB
          DO 60 K=1, NCA
            C(I,J) = C(I,J) + A(I,K) * B(K,J)
  60  CONTINUE

C     End of parallel region 
!$OMP END PARALLEL

C     Print results
      PRINT *, '******************************************************'
      PRINT *, 'Result Matrix:'
      DO 90 I=1, NRA
        DO 80 J=1, NCB
          WRITE(*,70) C(I,J)
  70      FORMAT(2x,f8.2,$)
  80      CONTINUE
          PRINT *, ' '
  90      CONTINUE
      PRINT *, '******************************************************'
      PRINT *, 'Done.'

      END

七、Get and print environment information

C******************************************************************************
C FILE: omp_getEnvInfo.f
C DESCRIPTION:
C   OpenMP Example - Get Environment Information - Fortran Version
C   The master thread queries and prints selected environment information.
C AUTHOR: Blaise Barney  7/06
C LAST REVISED: 07/12/06
C******************************************************************************

      PROGRAM GETINFO
     
      INTEGER NTHREADS, TID, OMP_GET_NUM_THREADS,
     +  OMP_GET_THREAD_NUM, OMP_GET_NUM_PROCS, OMP_GET_MAX_THREADS,
     +  OMP_IN_PARALLEL, OMP_GET_DYNAMIC, OMP_GET_NESTED,
     +  PROCS, MAXT

C     These are for AIX compilations
C     INTEGER INPAR, DYNAMIC, NESTED
C     These are for non-AIX compilations
      LOGICAL INPAR, DYNAMIC, NESTED
  
C     Start parallel region
!$OMP PARALLEL PRIVATE(NTHREADS, TID)

C     Obtain thread number
      TID = OMP_GET_THREAD_NUM()

C     Only master thread does this
      IF (TID .EQ. 0) THEN

        PRINT *, 'Thread',tid,'getting environment information'

C     Get environment information
        PROCS = OMP_GET_NUM_PROCS() 
        NTHREADS = OMP_GET_NUM_THREADS()
        MAXT = OMP_GET_MAX_THREADS()
        INPAR = OMP_IN_PARALLEL()
        DYNAMIC = OMP_GET_DYNAMIC()
        NESTED = OMP_GET_NESTED()

C     Print environment information
    
        PRINT *, 'Number of processors = ', PROCS
        PRINT *, 'Number of threads = ', NTHREADS
        PRINT *, 'Max threads = ', MAXT
        PRINT *, 'In parallel? = ', INPAR
        PRINT *, 'Dynamic threads enabled? = ', DYNAMIC
        PRINT *, 'Nested parallelism supported? = ', NESTED

      END IF

C     Done
!$OMP END PARALLEL

      END

八、Programs with bugs

(1)omp_bug1.f

C******************************************************************************
C FILE: omp_bug1.f
C DESCRIPTION:
C   This example attempts to show use of the PARALLEL DO construct.  However
C   it will generate errors at compile time.  Try to determine what is causing
C   the error.  See omp_bug1fix.f for a corrected version.
C AUTHOR: Blaise Barney  5/99
C LAST REVISED: 
C******************************************************************************

      PROGRAM WORKSHARE3

      INTEGER TID, OMP_GET_THREAD_NUM, N, I, CHUNKSIZE, CHUNK
      PARAMETER (N=50)
      PARAMETER (CHUNKSIZE=5) 
      REAL A(N), B(N), C(N)

!     Some initializations
      DO I = 1, N
        A(I) = I * 1.0
        B(I) = A(I)
      ENDDO
      CHUNK = CHUNKSIZE
            
!$OMP  PARALLEL DO SHARED(A,B,C,CHUNK) 
!$OMP& PRIVATE(I,TID) 
!$OMP& SCHEDULE(STATIC,CHUNK)

      TID = OMP_GET_THREAD_NUM()
      DO I = 1, N
         C(I) = A(I) + B(I)
         PRINT *,'TID= ',TID,'I= ',I,'C(I)= ',C(I)
      ENDDO

!$OMP  END PARALLEL DO

      END

(2)omp_bug1fix.f

C******************************************************************************
C FILE: omp_bug1fix.f
C DESCRIPTION:
C   This is a corrected version of the omp_bug1fix.f example. Corrections
C   include removing all statements between the PARALLEL DO construct and
C   the actual DO loop, and introducing logic to preserve the ability to 
C   query a thread's id and print it from inside the DO loop.
C AUTHOR: Blaise Barney  5/99
C LAST REVISED:
C******************************************************************************

      PROGRAM WORKSHARE4

      INTEGER TID, OMP_GET_THREAD_NUM, N, I, CHUNKSIZE, CHUNK
      PARAMETER (N=50)
      PARAMETER (CHUNKSIZE=5) 
      REAL A(N), B(N), C(N)
      CHARACTER FIRST_TIME

!     Some initializations
      DO I = 1, N
        A(I) = I * 1.0
        B(I) = A(I)
      ENDDO
      CHUNK = CHUNKSIZE
      FIRST_TIME = 'Y'
            
!$OMP  PARALLEL DO SHARED(A,B,C,CHUNK) 
!$OMP& PRIVATE(I,TID) 
!$OMP& SCHEDULE(STATIC,CHUNK)
!$OMP& FIRSTPRIVATE(FIRST_TIME) 

      DO I = 1, N
         IF (FIRST_TIME .EQ. 'Y') THEN
            TID = OMP_GET_THREAD_NUM()
            FIRST_TIME = 'N'
         ENDIF
         C(I) = A(I) + B(I)
         PRINT *,'TID= ',TID,'I= ',I,'C(I)= ',C(I)
      ENDDO

!$OMP  END PARALLEL DO

      END

(3)omp_bug2.f

C******************************************************************************
C FILE: omp_bug2.f
C DESCRIPTION:
C   Another OpenMP program with a bug
C AUTHOR: Blaise Barney  1/7/04
C LAST REVISED: 
C******************************************************************************

      PROGRAM BUG2
     
      INTEGER NTHREADS, I, TID, OMP_GET_NUM_THREADS,
     +        OMP_GET_THREAD_NUM
      REAL*8 TOTAL
  
C     Spawn parallel region
!$OMP PARALLEL 

C     Obtain thread number
      TID = OMP_GET_THREAD_NUM()
C     Only master thread does this
      IF (TID .EQ. 0) THEN
        NTHREADS = OMP_GET_NUM_THREADS()
        PRINT *, 'Number of threads = ', NTHREADS
      END IF
      PRINT *, 'Thread ',TID,'is starting...'

!$OMP BARRIER

C     Do some work
      TOTAL = 0.0
!$OMP DO SCHEDULE(DYNAMIC,10)
      DO I=1, 1000000
        TOTAL = TOTAL + I * 1.0
      END DO

      WRITE(*,100) TID,TOTAL
 100  FORMAT('Thread',I2,' is done! Total= ',E12.6)

!$OMP END PARALLEL

      END

(4)omp_bug3.f

C******************************************************************************
C FILE: omp_bug3.f
C DESCRIPTION:
C   Run time bug
C AUTHOR: Blaise Barney  01/09/04
C LAST REVISED: 06/28/05
C******************************************************************************

      PROGRAM BUG3

      INTEGER N, I, NTHREADS, TID, SECTION, OMP_GET_NUM_THREADS, 
     +        OMP_GET_THREAD_NUM
      PARAMETER (N=50)
      REAL A(N), B(N), C(N)

C     Some initializations
      DO I = 1, N
        A(I) = I * 1.0
        B(I) = A(I)
      ENDDO

!$OMP PARALLEL PRIVATE(C,I,TID,SECTION)
      TID = OMP_GET_THREAD_NUM()
      IF (TID .EQ. 0) THEN
        NTHREADS = OMP_GET_NUM_THREADS()
        PRINT *, 'Number of threads = ', NTHREADS
      END IF

C     Use barriers for clean output
!$OMP BARRIER
      PRINT *, 'Thread ',TID,' starting...'
!$OMP BARRIER

!$OMP SECTIONS
!$OMP SECTION
      SECTION = 1
      DO I = 1, N
         C(I) = A(I) * B(I)
      ENDDO
      CALL PRINT_RESULTS(C, TID, SECTION)

!$OMP SECTION
      SECTION = 2
      DO I = 1, N
         C(I) = A(I) + B(I)
      ENDDO
      CALL PRINT_RESULTS(C, TID, SECTION)

!$OMP END SECTIONS 

C     Use barrier for clean output
!$OMP BARRIER
      PRINT *, 'Thread',tid,' exiting...'

!$OMP END PARALLEL

      END



      SUBROUTINE PRINT_RESULTS(C, TID, SECTION)
      INTEGER TID, SECTION, N, I, J
      PARAMETER (N=50)
      REAL C(N)

      J = 1
C     Use critical for clean output
!$OMP CRITICAL
      PRINT *, ' '
      PRINT *, 'Thread',TID,' did section',SECTION
      DO I=1, N
        WRITE(*,100) C(I)
 100    FORMAT(E12.6,$)
        J = J + 1
        IF (J .EQ. 6) THEN
          PRINT *, ' '
          J = 1
        END IF
      END DO
      PRINT *, ' '
!$OMP END CRITICAL

!$OMP BARRIER
      PRINT *,'Thread',TID,' done and synchronized'

      END SUBROUTINE PRINT_RESULTS

(4)omp_bug4.f

C******************************************************************************
C FILE: omp_bug4.f
C DESCRIPTION:
C   This very simple program causes a segmentation fault.
C AUTHOR: Blaise Barney  01/09/04
C LAST REVISED: 
C******************************************************************************

      PROGRAM BUG4
     
      INTEGER N, NTHREADS, TID, I, J, OMP_GET_NUM_THREADS,
     +        OMP_GET_THREAD_NUM
      PARAMETER(N=1048)
      REAL*8 A(N,N)
  
C     Fork a team of threads with explicit variable scoping
!$OMP PARALLEL SHARED(NTHREADS) PRIVATE(I,J,TID,A)

C     Obtain/print thread info
      TID = OMP_GET_THREAD_NUM()
      IF (TID .EQ. 0) THEN
        NTHREADS = OMP_GET_NUM_THREADS()
        PRINT *, 'Number of threads = ', NTHREADS
      END IF
      PRINT *, 'Thread',TID,' starting...'

C     Each thread works on its own private copy of the array
      DO I=1,N
        DO J=1,N
          A(J,I) = TID + I + J
        END DO
      END DO

C     For confirmation
      PRINT *, 'Thread',TID,'done. Last element=',A(N,N)

C     All threads join master thread and disband
!$OMP END PARALLEL

      END

(5)omp_bug4fix.f

#!/bin/csh

#******************************************************************************
# FILE: omp_bug4fix
# DESCRIPTION:
#   This script is used to set the thread stack size limit to accomodate
#   the omp_bug4 example. The example code requires @16MB per thread. For
#   safety, this script sets the stack limit to 20MB. Note that the way
#   to do this differs between architectures. 
# AUTHOR: Blaise Barney  01/12/04
# LAST REVISED: 
#*****************************************************************************/

# This is for all systems
limit stacksize unlimited

# This is for IBM AIX systems
setenv XLSMPOPTS "stack=20000000"

# This is for Linux systems 
setenv KMP_STACKSIZE 20000000

# This is for HP/Compaq Tru64 systems
setenv MP_STACK_SIZE 20000000

# Now call the executable - change the name to match yours
omp_bug4

(6)omp_bug5.f

C******************************************************************************
C FILE: omp_bug5.f
C DESCRIPTION:
C   Using SECTIONS, two threads initialize their own array and then add 
C   it to the other's array, however a deadlock occurs.
C AUTHOR: Blaise Barney  01/09/04
C LAST REVISED:
C******************************************************************************

      PROGRAM BUG5
     
      INTEGER*8 LOCKA, LOCKB
      INTEGER NTHREADS, TID, I, 
     +        OMP_GET_NUM_THREADS, OMP_GET_THREAD_NUM
      PARAMETER (N=1000000)
      REAL A(N), B(N), PI, DELTA
      PARAMETER (PI=3.1415926535)
      PARAMETER (DELTA=.01415926535)

C     Initialize the locks
      CALL OMP_INIT_LOCK(LOCKA)
      CALL OMP_INIT_LOCK(LOCKB)

C     Fork a team of threads giving them their own copies of variables
!$OMP PARALLEL SHARED(A, B, NTHREADS, LOCKA, LOCKB) PRIVATE(TID)

C     Obtain thread number and number of threads
      TID = OMP_GET_THREAD_NUM()
!$OMP MASTER
      NTHREADS = OMP_GET_NUM_THREADS()
      PRINT *, 'Number of threads = ', NTHREADS
!$OMP END MASTER
      PRINT *, 'Thread', TID, 'starting...'
!$OMP BARRIER

!$OMP SECTIONS

!$OMP SECTION
      PRINT *, 'Thread',TID,' initializing A()'
      CALL OMP_SET_LOCK(LOCKA)
      DO I = 1, N
         A(I) = I * DELTA
      ENDDO
      CALL OMP_SET_LOCK(LOCKB)
      PRINT *, 'Thread',TID,' adding A() to B()'
      DO I = 1, N
         B(I) = B(I) + A(I)
      ENDDO
      CALL OMP_UNSET_LOCK(LOCKB)
      CALL OMP_UNSET_LOCK(LOCKA)

!$OMP SECTION
      PRINT *, 'Thread',TID,' initializing B()'
      CALL OMP_SET_LOCK(LOCKB)
      DO I = 1, N
         B(I) = I * PI
      ENDDO
      CALL OMP_SET_LOCK(LOCKA)
      PRINT *, 'Thread',TID,' adding B() to A()'
      DO I = 1, N
         A(I) = A(I) + B(I)
      ENDDO
      CALL OMP_UNSET_LOCK(LOCKA)
      CALL OMP_UNSET_LOCK(LOCKB)

!$OMP END SECTIONS NOWAIT

      PRINT *, 'Thread',TID,' done.'

!$OMP END PARALLEL

      END

(7)omp_bug5fix.f

C******************************************************************************
C FILE: omp_bug5fix.f
C DESCRIPTION:
C   The problem in omp_bug5.f is that the first thread acquires locka and then
C   tries to get lockb before releasing locka. Meanwhile, the second thread
C   has acquired lockb and then tries to get locka before releasing lockb.
C   This solution overcomes the deadlock by using locks correctly.
C AUTHOR: Blaise Barney  01/09/04
C LAST REVISED:
C******************************************************************************

      PROGRAM BUG5
     
      INTEGER*8 LOCKA, LOCKB
      INTEGER NTHREADS, TID, I, 
     +        OMP_GET_NUM_THREADS, OMP_GET_THREAD_NUM
      PARAMETER (N=1000000)
      REAL A(N), B(N), PI, DELTA
      PARAMETER (PI=3.1415926535)
      PARAMETER (DELTA=.01415926535)

C     Initialize the locks
      CALL OMP_INIT_LOCK(LOCKA)
      CALL OMP_INIT_LOCK(LOCKB)

C     Fork a team of threads giving them their own copies of variables
!$OMP PARALLEL SHARED(A, B, NTHREADS, LOCKA, LOCKB) PRIVATE(TID)

C     Obtain thread number and number of threads
      TID = OMP_GET_THREAD_NUM()
!$OMP MASTER
      NTHREADS = OMP_GET_NUM_THREADS()
      PRINT *, 'Number of threads = ', NTHREADS
!$OMP END MASTER
      PRINT *, 'Thread', TID, 'starting...'
!$OMP BARRIER

!$OMP SECTIONS

!$OMP SECTION
      PRINT *, 'Thread',TID,' initializing A()'
      CALL OMP_SET_LOCK(LOCKA)
      DO I = 1, N
         A(I) = I * DELTA
      ENDDO
      CALL OMP_UNSET_LOCK(LOCKA)
      CALL OMP_SET_LOCK(LOCKB)
      PRINT *, 'Thread',TID,' adding A() to B()'
      DO I = 1, N
         B(I) = B(I) + A(I)
      ENDDO
      CALL OMP_UNSET_LOCK(LOCKB)

!$OMP SECTION
      PRINT *, 'Thread',TID,' initializing B()'
      CALL OMP_SET_LOCK(LOCKB)
      DO I = 1, N
         B(I) = I * PI
      ENDDO
      CALL OMP_UNSET_LOCK(LOCKB)
      CALL OMP_SET_LOCK(LOCKA)
      PRINT *, 'Thread',TID,' adding B() to A()'
      DO I = 1, N
         A(I) = A(I) + B(I)
      ENDDO
      CALL OMP_UNSET_LOCK(LOCKA)

!$OMP END SECTIONS NOWAIT

      PRINT *, 'Thread',TID,' done.'

!$OMP END PARALLEL

      END

(8)omp_bug6.f

C******************************************************************************
C FILE: omp_bug6.f
C DESCRIPTION:
C   This program compiles and runs fine, but produces the wrong result.
C   Compare to omp_orphan.f.
C AUTHOR: Blaise Barney  6/05
C LAST REVISED: 06/27/05
C******************************************************************************

      PROGRAM ORPHAN
      COMMON /DOTDATA/ A, B
      INTEGER I, VECLEN
      REAL*8 SUM
      PARAMETER (VECLEN = 100)
      REAL*8 A(VECLEN), B(VECLEN)

      DO I=1, VECLEN
         A(I) = 1.0 * I
         B(I) = A(I)
      ENDDO
      SUM = 0.0
!$OMP PARALLEL SHARED (SUM)
      CALL DOTPROD
!$OMP END PARALLEL
      WRITE(*,*) "Sum = ", SUM
      END



      SUBROUTINE DOTPROD
      COMMON /DOTDATA/ A, B
      INTEGER I, TID, OMP_GET_THREAD_NUM, VECLEN
c     REAL*8 SUM
      PARAMETER (VECLEN = 100)
      REAL*8 A(VECLEN), B(VECLEN)

      TID = OMP_GET_THREAD_NUM()
!$OMP DO REDUCTION(+:SUM)
      DO I=1, VECLEN
         SUM = SUM + (A(I)*B(I))
         PRINT *, '  TID= ',TID,'I= ',I
      ENDDO
      RETURN
      END

 

你可能感兴趣的:(fortran)