When do Fortran redistributables go out of scope when loaded as a shared library?

I am calling a fortran routine from R as part of a more complex optimization task. At present, the subroutine is autonomous - with the input of the current values โ€‹โ€‹of the parameters and the output of the evaluation functions and gradient terms. Now I want to initialize the allocated array as a shared module variable (before optimization) to be used (but not changed) by the subroutine during optimization.

In this context, when is a shared distributed array going out of scope or removed?

A naive reading of the memory management section in the Fortran wikibook suggests that module variables should be persisted (possibly even after the program has been executed).

Number of sources I read that the array being allocated will be automatically deallocated when it goes out of scope. This also happens for module variables, and when will it happen?

I found the number questions , but I was unable to place them in the context of both module variables and shared library loading.

Edit:

A minimal example of a fortran module. The selected array works as expected in the fortran program. In practice, both init()

and eval()

will be wrapped with R functions ( init_wrap()

and eval_wrap()

) and called from R. I want to confirm that the allocated variable is y

guaranteed not to be out of scope or deleted, but is test_module

loaded as a shared library.

module test_module

  double precision, allocatable, dimension(:,:) :: y

  contains

    subroutine init() bind(C, name = "init_")

      if (.not. allocated(y) ) then
        allocate(y(1,1))
      end if

      y = 1
    end subroutine init

    subroutine eval(x, z) bind(C, name = "eval_")

      double precision, intent(in) :: x
      double precision, intent(out) :: z

      z = x + y(1,1)

    end subroutine eval

end module test_module

! Program added for testing purposes only, 
! module is used as shared library
program test_program

   use test_module

   double precision :: x, z

   ! Initialize allocatable array
   call init()

   ! Use allocatable array during optimization
   x = 1
   call eval(x, z)

   x = 2
   call eval(x, z)

   print *, z

end program test_program

      

Edit 2:

I created a skeleton package on github that simulates how I use the fortran code: https://github.com/ssokolen/fortran.test

The following R code works as I need it to (the allocated array retains its value between calls eval_wrap()

), but I'm still hoping to get a definitive answer when the allocated module variable goes out of scope when loaded as a shared library (or the answer that says that there is no common behavior).

library(devtools)
install_github('ssokolen/fortran.test')
library(fortran.test)
init_wrap()
eval_wrap(1)
eval_wrap(2)

      

+3


source to share


1 answer


Dynamically loaded libraries are outside the Fortran standard. Which comes from the whole "processor", which is a complex of the Fortran compiler, operating system, linker, etc.

On Linux and other POSIX operating systems, if you unload a library from memory, it will go out of scope. This simple test case demonstrates that:

module test_module

  double precision, allocatable, dimension(:,:) :: y

  contains

    subroutine init() bind(C, name = "init_")
      print *, "init_"
      if (.not. allocated(y) ) then
        allocate(y(1,1))
      end if

      y = 1
    end subroutine init

    subroutine eval(x, z) bind(C, name = "eval_")

      double precision, intent(in) :: x
      double precision, intent(out) :: z

      if (.not. allocated(y) ) error stop("not allocated!")
      z = x + y(1,1)
      print*, "success"
    end subroutine eval

end module test_module

      

And C calls the library:



#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>

int main(){

  void *handle = dlopen("/home/lada/f/testy/stackoverflow/dltest.so",RTLD_NOW);

  void (*init_)() = (void (*)())dlsym(handle, "init_");
  init_();

  double x=0,y=0;
  void (*eval_)(double x, double z) = (void (*)())dlsym(handle, "eval_");      
  eval_(x, y);

  dlclose(handle);
  handle = dlopen("./dltest.so",RTLD_NOW);

  eval_ = (void (*)())dlsym(handle, "eval_");
  eval_(x, y);

  return 0;

}

      

And run:

> gfortran -shared -fPIC -o dltest.so dltest.f90
> gcc -ggdb  dltest.c -ldl
> ./a.out 
 init_
 success
ERROR STOP not allocated!

      

The array is no longer allocated after dlclose()

and dlopen()

. You must make sure that R does not unload the library from memory.

+1


source







All Articles