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

MKL sjacobix void pointer problem

David_Mccabe
Beginner
431 Views

Hi there,

I am having problems calling the sjacobix MKL subroutine when passing a void pointer to my resource type for use in my cost function.  I have tried following the example program in which the final dummy argument of the extended_powell is  type(my_data) :: user_data, and the actual argument is the address of the resource type with a pass by value directive %VAL(LOC(m_data))

res = sjacobix(cost_function, n, m, fjac, x, eps(1), %val(loc(this)))

    subroutine cost_function(m, n, x, f, myARMA)
    
        use MKLMatrix_module
        use ARMA_data
        use iso_c_binding
    
        integer :: m                            ! dimension of f
        integer :: n                            ! dimension of x
        real(WP), dimension(n)  :: x            ! input values
        real(WP), dimension(m)  :: f            ! output values (residuals)
        type(ARMA)              :: myARMA         ! ARMA model (& Training Data)

        ...

    end subroutine cost_function

This doesn't compile and I receive the following error diagnostic...

error #7065: The characteristics of dummy argument 5 of the associated actual procedure differ from the characteristics of dummy argument 5 of the dummy procedure.

I have been trying to find a workaround and have managed to compile by passing the actual argument int(loc(this),c_intptr_t) to an integer dummy argument integer(c_intptr_t) :: ipRes.  I have tried to associate a pointer to my own resource type type(ARMA) to this address via an iso_c_binding type(c_ptr) and although this seems to pass the resource to my cost function, this seems to be corrupting the program stack.  My cost function & calling code now look something like this...

res = sjacobix(cost_function, n, m, fjac, x, eps(1), int(loc(this),c_intptr_t))
    subroutine cost_function(m, n, x, f, ipRes)
    
        use MKLMatrix_module
        use ARMA_data
        use iso_c_binding
    
        integer :: m                            ! dimension of f
        integer :: n                            ! dimension of x
        real(WP), dimension(n)  :: x            ! input values
        real(WP), dimension(m)  :: f            ! output values (residuals)
        integer(c_intptr_t)     :: ipRes        ! int(void*) to resources
        type(c_ptr)             :: pRes         ! void* to resources
        type(ARMA),pointer      :: pARMA        ! ARMA model (& Training Data)

        ! associate type with raw pointer address ~ 
        pRes = transfer(ipRes,pRes)             ! convert raw 4 byte address into a c_ptr
        call c_f_pointer(pRes,pARMA)            !  associate pARMA with  c_ptr
        ...
    end subroutine cost_function

 

Please could somebody advise me on what to try next?  Additional info: Package ID: w_fcompxe_2015.2.179

0 Kudos
3 Replies
Steven_L_Intel1
Employee
431 Views

I think you want to go back to passing %VAL(LOC(data)) and then do this:

subroutine cost_function(m, n, x, f, ipRes)

    use MKLMatrix_module
    use ARMA_data
    use iso_c_binding

    integer :: m                            ! dimension of f
    integer :: n                            ! dimension of x
    real(WP), dimension(n)  :: x            ! input values
    real(WP), dimension(m)  :: f            ! output values (residuals)
    integer(c_intptr_t)     :: ipRes        ! int(void*) to resources
    type(ARMA),pointer      :: pARMA        ! ARMA model (& Training Data)

    ! associate type with raw pointer address ~ 
    call c_f_pointer(C_LOC(ipRes),pARMA)            !  associate pARMA with  c_ptr
    ...
end subroutine cost_function

 

0 Kudos
David_Mccabe
Beginner
431 Views

Thanks Steve,

I knew using transfer was the wrong thing to do.  I thought c_loc would have returned the address of the register holding the dummy which was being past.  Here it is casting the value of the scalar dummy into an address of type c_ptr.

On a side note, it looks like the my memory issue was actually caused by something else.

0 Kudos
jimdempseyatthecove
Honored Contributor III
431 Views

>> I thought c_loc would have returned the address of the register holding the dummy

On IA32 and Intel64 processors, registers do not have addresses. This said, depending on the calling convention (for architecture), the DUMMY variable being passed in register, may/will have stack space reserved for it in the event that the register will have to be saved and restored. This stack reserve space will have an address (but the contents are not initially written). The compiler "should" flush the register to RAM in the event you take the LOC/C_LOC of the dummy but some assumptions by the programmer may circumvent this (e.g. assuming memory order on stack of dummys m,n,x,f,ipRes)

Also, a limited number of first arguments are capable of being passed by register. Do not rely on a specific number as this is subject to change.

Jim Dempsey

0 Kudos
Reply