Quantcast
Channel: Intel® Fortran Composer XE
Viewing all articles
Browse latest Browse all 1424

Support for passing internal procedures fails in parallel environment (not thread safe)

$
0
0

Fortran 2008 allows passing internal procedures as actual arguments and Intel Fortran supports this. A passed internal procedure can see host data so it makes it easier to write generic functions like a function integrator. In this test the host data is an element of an allocatable array. I passed the host data to my function integrator so that I could compare to see if it was the same data that could be seen by host association.

The test shows the data often does not match when using OpenMP. Try a break point on the continue statement.

Also note the access violation at the end which I don't understand.

module someFairlyOrdinaryCode
   implicit none
   contains

subroutine integrator(k, answer)
   use omp_lib
   real, intent(in) :: k
   real, intent(out) :: answer
  
   !Normally host association would be used to obtain additional data required by f(x)
   !Passing k for test purposes
   call integrateAnyFunction(f, k, 0.0, 1.0, answer)
  
contains
   real function f(x, kPassedValue)
      real, intent(in) :: x, kPassedValue
        
      !k is not visible in debugger so copy to local
      real hostK
      hostK = k
        
      !Put break point on continue
      if (hostK /= kPassedValue) then
         continue
      end if
      f = k*x
   end function
end subroutine

subroutine integrateAnyFunction(f, k, a, b, answer)
   interface
      real function f(x, k)
         real, intent(in) :: x, k
      end function
   end interface
   real, intent(in) :: a, b, k
   real, intent(out) :: answer
  
   real h, x1, x2
   integer i
   answer = 0.0
   h = (b - a)/9
   do i = 1, 10
      x1 = a + h*(i-1)
      x2 = x1 + h
      answer = answer + (f(x1, k) + f(x2, k))*h/2
   end do
end subroutine

end module

program TestOpenMPThatTookAYearToFind
   use ifport
   use someFairlyOrdinaryCode
   integer numTimes
   real, allocatable :: k(:), answer(:)
   integer i, j

   do j = 1, 2000
      numTimes = int(rand(0)*20.0) + 1
      allocate(k(numTimes), answer(numTimes))
      do i = 1, numTimes
         k(i) = i
      end do
      !$OMP PARALLEL DO
      do i = 1, numTimes
         call integrator(k(i), answer(i))
      end do
      !$OMP END PARALLEL DO
      deallocate(k, answer)
   end do
end program

 


Viewing all articles
Browse latest Browse all 1424

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>