Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

equivalent of LOC

abhimodak
New Contributor I
580 Views

This question is "out of scope" for Intel Fortran. But I am just taking a chance....

Since IVF still doesn't support procedure pointers and type bound procedures, I have been using the Cray style pointers, as suggested by Steve,to fake this. I used intrinsic function LOC to get the address of an external procedure.

However, the other platform that we need to support is IBM and unfortunately LOC intrinsic on that platform is not valid for external procedures. Does anyody know a "common set" that can be used on these two platforms to mimick procedure pointers and type bound procedures?

Abhi

0 Kudos
3 Replies
Steven_L_Intel1
Employee
580 Views
Does the IBM compiler support passing a variable by value? Which IBM compiler are you using? xlf is ahead of Intel Fortran in F2003 support.
0 Kudos
jimdempseyatthecove
Honored Contributor III
580 Views

Abhi,

Considerusing the attribute external. From my QuickThread tool see how the test are run by way of address of function.

Look downnear bottom of code for call to RunTest(...) then look at interface in module (sorry about tabbing as paste code removes that)

This would require some adaptaton to call proceedures (as seperate process in seperate address space) but the sample code should a good basis for how you would do this.

Jim Dempsey

! SimpleArray.f90

!

! FUNCTIONS:

! SimpleArray - Entry point of console application.

!

!****************************************************************************

!

! PROGRAM: SimpleArray

!

! PURPOSE: Entry point for the console application.

!

!****************************************************************************

module

SimpleArray_mod

use PerformanceCounter

use QuickThreadInterfaces

! Declare application Performance Counter

type(T_PERFORMANCECOUNTER) :: ThePerformanceCounter

integer :: ArraySize

integer :: ArraySizeBegin = 1000

integer :: ArraySizeLimit = 1000000

! TestRunTimeDesired

! Number of seconds of run time desired for single threaded test

real(8) :: TestRunTimeDesired = 10.

real(8) :: SingleThreadedRunTime

! NumberOfIterations

! Calculated at initialization to produce single threaded run time

! of TestRunTimeDesired seconds

integer :: NumberOfIterations

! isTemporal = .true. if array processing has temporal characteristics

! isTemporal = .false. if array processing has no temporal characteristics

logical :: isTemporal

real(8), allocatable :: A(:) ! Allocated to ArraySize

real(8), allocatable :: B(:) ! Allocated to ArraySize

real(8), allocatable :: C(:) ! Allocated to ArraySize

! Declare the interface to your copy of QuickThreadQueueMainTemplate

interface

integer(DWORD) function QueueMain(MainCode)

use kernel32

implicit none

logical, external :: MainCode

end function QueueMain

end interface

interface

subroutine RunTest(Test, isQuickThread, Name)

external :: Test

logical :: isQuickThread

character*(*) :: Name

end subroutine RunTest

end interface

! Define interface to DoSimpleArraySlice

interface

subroutine DoSimpleArraySlice(iFrom, iTo)

!DEC$ ATTRIBUTES VALUE :: iFrom

integer :: iFrom

!DEC$ ATTRIBUTES VALUE :: iTo

integer :: iTo

end subroutine DoSimpleArraySlice

end interface

end module

SimpleArray_mod

program

SimpleArray

use SimpleArray_mod

implicit none

! Variables

integer :: i, j

real(8) :: SingleThreadRunTimeInSeconds

real(8) :: OpenMPRunTimeInSeconds

real(8) :: QuickThreadRunTimeInSeconds

real(8) :: PerformanceGain

! Test subroutines

exter nal :: SingleThreadTest

external :: OpenMPTest

external :: QuickThreadTest

! Body of SimpleArray

write(*,*) 'SimpleArray'

write(*,*) 'Specified runtime', TestRunTimeDesired

write(*,*) ''

ArraySize = 0

do while(ArraySize .lt. ArraySizeLimit)

if(ArraySize .eq. 0) then

ArraySize = ArraySizeBegin

else

ArraySize =

min(ArraySize*2, ArraySizeLimit)

endif

write(*,*) 'ArraySize = ', ArraySize

! allocate the arrays

allocate(A(ArraySize))

allocate(B(ArraySize))

allocate(C(ArraySize))

! initialize arrays B and C to random numbers

call RANDOM_NUMBER(B)

call RANDOM_NUMBER(C)

! Calibrate iteration count to produce a single threaded

! run time of TestRunTimeDesired seconds

! Perform calibration after allocation and initialization of arrays

call CalibrateRuntime

SingleThreadedRunTime = 0.

call RunTest(SingleThreadTest, .false., "Single Threaded")

call RunTest(OpenMPTest, .false., "OpenMP")

isTemporal = .true.

write(*,*) "Temporal", isTemporal

call RunTest(QuickThreadTest, .true., "QuickThread")

isTemporal = .false.

write(*,*) "Temporal", isTemporal

call RunTest(QuickThreadTest, .true., "QuickThread")

! return memory

deallocate(A)

deallocate(B)

deallocate(C)

end do

!DEC$ IF DEFINED(_DEBUG)

! If debugging, pause to permit reading of console window before exit

write(*,*) ""

pause

!DEC$ ENDIF

end

program SimpleArray

! Calibrate iteration count to produce a single threaded

! run time of TestRunTimeDesired seconds

subroutine

CalibrateRuntime

use SimpleArray_mod

implicit none

! Initialize the Performance Counter code

call PerformanceCounterInit

ThePerformanceCounter.RunTimeInSeconds = 0.

NumberOfIterations = 1

do while(ThePerformanceCounter.RunTimeInSeconds .lt. 0.5)

! First order Estimation accuracy to ~1%

! Make a run of NumberOfIterations

call PerformanceCounterStart(ThePerformanceCounter)

call SingleThreadTest

call PerformanceCounterEnd(ThePerformanceCounter)

! Compute the number of iterations to run for 1 second

NumberOfIterations =

int(dble(NumberOfIterations) * 1.0_8 / ThePerformanceCounter.RunTimeInSeconds)

end do

! Compute the number of iterations to run for TestRunTimeDesired

NumberOfIterations =

int(dble(NumberOfIterations) * TestRunTimeDesired / ThePerformanceCounter.RunTimeInSeconds)

end subroutine

CalibrateRuntime

subroutine

RunTest(Test, isQuickThread, Name)

use SimpleArray_mod

implicit none

external :: Test

logical :: isQuickThread

character *(*) :: Name

integer :: iTrash

write(*,100) Name

100

format(A15,' ',$)

call PerformanceCounterStart(ThePerformanceCounter)

if(isQuickThread) then

! ignore error

iTrash = QueueMain(Test)

else

call Test

endif

call PerformanceCounterEnd(ThePerformanceCounter)

if(SingleThreadedRunTime .eq. 0.) SingleThreadedRunTime = ThePerformanceCounter.RunTimeInSeconds

write(*,200) ThePerformanceCounter.RunTimeInSeconds, (SingleThreadedRunTime / ThePerformanceCounter.RunTimeInSeconds) * 100.0_8

200

format(F15.12, F15.9,'%')

end subroutine

RunTest

subroutine

SingleThreadTest

use SimpleArray_mod

implicit none

! Local Variables

integer :: i, j

! Code

do i=1, NumberOfIterations

do j=1, size(A)

A(j) = B(j) + C(j)

end do

end do

end subroutine

SingleThreadTest

subroutine

OpenMPTest

use SimpleArray_mod

implicit none

! Local Variables

integer :: i, j

! Code

do i=1, NumberOfIterations

!$OMP PARALLEL DO

do j=1, size(A)

A(j) = B(j) + C(j)

end do

!$OMP END PARALLEL DO

end do

end subroutine

OpenMPTest

subroutine

QuickThreadTest

use SimpleArray_mod

use QuickThreadInterfaces

implicit none

! Local Variables

! Stack local control structure

type(T_QuickThreadControlStructure) :: qtControl

integer :: i

! code

do i=1, NumberOfIterations

! Slice the array processing by number of worker threads

! across range of 1 to size of array A (B, and C)

call QuickThreadQueueDo(qtControl, DoSimpleArraySlice, 1, size(A))

if(isTemporal) call QuickThreadWaitTillDone(qtControl)

end do

if(.not. isTemporal) call QuickThreadWaitTillDone(qtControl)

end subroutine

QuickThreadTest

! DoSimpleArraySlice

! Perform work on slice of arrays A, B, and C

subroutine

DoSimpleArraySlice(iFrom, iTo)

use SimpleArray_mod

implicit none

!DEC$ ATTRIBUTES VALUE :: iFrom

integer :: iFrom

!DEC$ ATTRIBUTES VALUE :: iTo

integer :: iTo

! Local Variables

integer :: j

do j=iFrom, iTo

A(j) = B(j) + C(j)

end do

end subroutine

DoSimpleArraySlice

0 Kudos
abhimodak
New Contributor I
580 Views

Hi Steve and Jim

Thanks for you answer.

Attached code snippet shows exactly what I am trying to do.

I (sadly) know that XLF is way ahead of Intel Fortran but I must usethe same code on both platforms.

Function %VAL and %REF are available on IBM. LOC is also available but unlike Intel, it cannot be used for a procedure. IBM cannot use cray pointers with procedure name either.

I will try to understand Jim's code.

Sincerely

Abhi

(Virus scan in progress ...)
0 Kudos
Reply