Hi list,
I’m trying to register a pointer to a Fortran field to a C-subroutine. The idea is that C-subroutine can store the address of the field and then use the pointer at a later point in time (i.e. when the gcl_DoExchange() method is called in the example below). A stripped down version of the code which contains the essential parts are shown below. When I run the program with the PGI compiler using debugging options, everything is fine. When I run the program using full optimization, I get an error. The stdout messages give a hint what is going wrong…
HALO_DBG: called gcl_AddNonDycoreFieldToHaloExchange with t_snow_new @0x9F4AD30
Trying to add non-dycore field @0x7fffe7279a30 to halo exchange
Somehow it seems that the gcl_RegisterField_Wrapper() call is generating a temporary copy of the field on the stack, since the memory address which is being received on the C++ side (Message: Trying to add…) does not match the one on the Fortran side (Message: HALO_DBG: called …). Is there a way to force Fortran compilers to not generate temporary copies of fields along a deep call chain in order to make sure that the correct pointer is being received on the C++ side? Is it actually legal that the Fortran compiler generates a temporary copy of the field when C_LOC(field) is being supplied to a subroutine that is bound to the C-routine?
Any hints are highly appreciated!
Kind regards,
Oli
======================================
PROGRAM test
IMPLICIT NONE
REAL, TARGET, ALLOCATABLE :: t_snow (:,:,:)
INTEGER :: ie, je, ntlev, nnew
ie = 40; je = 50; ntlev = 2; nnew = 2
ALLOCATE(t_snow(ie,je,ntlev))
CALL gcl_RegisterField(t_snow(:,:,nnew), "t_snow_new”)
CALL gcl_DoExchange()
DEALLOCATE(t_snow)
END PROGRAM test
SUBROUTINE gcl_RegisterField(field, fieldName)
! arguments
CHARACTER(LEN=*) :: fieldName
REAL, TARGET :: field(:,:)
! locals
CHARACTER(LEN=32) :: hexstr
! external functions
INTERFACE
SUBROUTINE gcl_RegisterField_Wrapper(isize, jsize, ksize, field, fieldName) &
BIND(c, name='communicationwrapper_register_field')
USE, INTRINSIC :: iso_c_binding
INTEGER(C_INT), value :: isize, jsize ! number of halo lines to be exchanged
TYPE(C_PTR), value :: field
CHARACTER(KIND=C_CHAR), DIMENSION(*) :: fieldName ! name of the field to be added
END SUBROUTINE gcl_RegisterField_Wrapper
END INTERFACE
! debug
IF (debug) THEN
write(hexstr,'(Z)') loc(field(1,1))
write(*,*) 'HALO_DBG: called gcl_RegisterField with '//TRIM(fieldName)//' @0x'//TRIM(ADJUSTL(hexstr))
ENDIF
! call wrapper
!$acc data present(field)
!$acc host_data use_device(field)
CALL gcl_RegisterField_Wrapper(SIZE(field,1), SIZE(field,2), C_LOC(field), TRIM(fieldName) // C_NULL_CHAR)
!$acc end host_data
!$acc end data
END SUBROUTINE gcl_RegisterField
|