#1
  1. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,995
    Rep Power
    481

    FORTRAN parallel


    Issue: My effort to make the program use 2 cores at the same time isn't working. Please help! I'll give you credit in the rosetta code wiki page discussion, or you can of course modify the FORTRAN entry directly.

    I wrote determinant and permanent by cofactor. Now I'd like to have the loop run in parallel. Matrix size of 11 by 11 runs for long enough to watch my cpu monitor but not long enough for coffee break.

    Build:
    Code:
    gfortran -std=f2008 -Wall -ffree-form -fall-intrinsics g.f08 -o g
    Here's my parallel version of the program. Reads the file /tmp/a , shown below. You may need to change the open statement for your system.

    For the run I attempt to set the number of threads to the number of cores my cpu has. The program runs on only one core---it's not working. Setting the variable on the bash command line affects the environment in which the program runs.
    $ OMP_NUM_THREADS=2 ./g
    I'm not aware of other environmental parameters.

    The functions det and detBackEnd are similar. det is supposed to make the first expansion by cofactors parallel.

    File g.f08 :
    Code:
    ! compute permanent or determinant
    program f
    
      implicit none
      integer, parameter :: N = 11
      real, dimension(3,3) :: j, m
      real, dimension(N,N) :: timeme
      integer :: i, k
      data j/ 2,-1, 1,-1,-2, 1,-1,-1,-1/
      data m/2, 9, 4, 7, 5, 3, 6, 1, 8/
    
      open(unit=7,file='/tmp/a')
      read(7,'(11f8.4)')((timeme(i, k),i=1,N), k=1,N)
      close(7)
      write(6,*) 'j example, determinant: ',det(j,3,-1)
      write(6,*) 'j example, permanent:   ',det(j,3,1)
      write(6,*) 'maxima, determinant:    ',det(m,3,-1)
      write(6,*) 'maxima, permanent:      ',det(m,3,1)
      write(6,*) 'parallel timing, det:   ',det(timeme, N, -1)
    
    contains
    
      function det(a,n,permanent) result(accumulation)
        integer, intent(in) :: n, permanent
        real, dimension(n,n), intent(in) :: a
        real, dimension(n-1, n-1) :: b
        real :: accumulation, cofactor
        integer :: i, sgn
        if (n .eq. 1) then
          accumulation = a(1,1)
        else
    !$OMP PARALLEL PRIVATE(i, b, sgn, cofactor) SHARED(n, a, accumulation)
          accumulation = 0
          sgn = 1
    !$OMP DO
          do i=1, n
            b(:, :(i-1)) = a(2:, :i-1)
            b(:, i:) = a(2:, i+1:)
            cofactor = sgn * a(1, i) * detBackEnd(b, n-1, permanent)
            sgn = sgn * permanent
    !$OMP CRITICAL
            accumulation = accumulation + cofactor
    !$OMP END CRITICAL
          enddo
    !$OMP END DO
    !$OMP END PARALLEL
        endif
        
      end function det
    
      recursive function detBackEnd(a,n,permanent) result(accumulation)
        integer, intent(in) :: n, permanent
        real, dimension(n,n), intent(in) :: a
        real, dimension(n-1, n-1) :: b
        real :: accumulation
        integer :: i, sgn
        if (n .eq. 1) then
          accumulation = a(1,1)
        else
          accumulation = 0
          sgn = 1
          do i=1, n
            b(:, :(i-1)) = a(2:, :i-1)
            b(:, i:) = a(2:, i+1:)
            accumulation = accumulation + sgn * a(1, i) * detBackEnd(b, n-1, permanent)
            sgn = sgn * permanent
          enddo
        endif
      end function detBackEnd
    
    end program f
    Data file /tmp/a
    Code:
     -0.9233 -0.3414 -0.3287  0.9719 -0.8832 -0.4353  0.3837  0.4589  0.5411 -0.9975 -0.1662
     -0.6250 -0.5065  0.7912  0.5142 -0.8105  0.1864 -0.7610 -0.7304 -0.2156 -0.5211  0.4737
      0.1926  0.9245  0.0578  0.1729  0.7525  0.6637 -0.5166 -0.1196  0.0427 -0.1227 -0.6897
     -0.2026 -0.9986 -0.7234 -0.5622 -0.0043  0.6622 -0.0391  0.2190  0.4439  0.9920  0.4930
     -0.2025 -0.1755  0.7863  0.0606  0.2410 -0.7572 -0.7954  0.0174 -0.9300 -0.8940  0.2355
     -0.5171  0.1820 -0.9027 -0.8529  0.2121  0.6141  0.0306 -0.2867  0.9090  0.6046  0.7202
     -0.2446 -0.1787 -0.9501 -0.0120 -0.1054  0.0532  0.5334  0.1750  0.9033  0.1564  0.5434
     -0.7623 -0.4289  0.7095 -0.2523 -0.4879 -0.1403  0.2641 -0.1942 -0.0715  0.6027 -0.6333
      0.6481 -0.3772  0.7643 -0.7742  0.2458 -0.5631 -0.5286  0.4351  0.4264 -0.9650 -0.7233
     -0.2791 -0.6675 -0.6775  0.6349  0.5573 -0.2360 -0.9998 -0.0394  0.3787  0.3479  0.9218
      0.6547  0.6608  0.5983  0.0474 -0.8387  0.4142 -0.3906  0.2679  0.2319  0.9772  0.6077
    Thank you,
    Dave.
    Last edited by b49P23TIvg; May 21st, 2013 at 04:40 PM. Reason: spring cleaning
    [code]Code tags[/code] are essential for python code and Makefiles!
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,995
    Rep Power
    481

    Solved.


    gfortran needs the -fopenmp option to produce the parallel code.

    gfortran -std=f2008 -Wall -fopenmp -ffree-form -fall-intrinsics g.f08 -o g


    Elapsed time time is slightly less with two threads, cpu use is much greater.

    Code:
    $ OMP_NUM_THREADS=2 time ./g    # two threads
     j example, determinant:    7.00000000    
     j example, permanent:      5.00000000    
     maxima, determinant:      -360.000000    
     maxima, permanent:         900.000000    
     parallel timing, det:      8.64285374    
    12.06user 0.00system 0:06.90elapsed 174%CPU (0avgtext+0avgdata 1184maxresident)k
    0inputs+0outputs (0major+360minor)pagefaults 0swaps
    $ OMP_NUM_THREADS=1 time ./g    # two threads
     j example, determinant:    7.00000000    
     j example, permanent:      5.00000000    
     maxima, determinant:      -360.000000    
     maxima, permanent:         900.000000    
     parallel timing, det:      8.64285374    
    7.28user 0.00system 0:07.30elapsed 99%CPU (0avgtext+0avgdata 1148maxresident)k
    0inputs+0outputs (0major+351minor)pagefaults 0swaps
    [code]Code tags[/code] are essential for python code and Makefiles!

IMN logo majestic logo threadwatch logo seochat tools logo