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

FORTRAN shared module data in a DLL

James_S_8
Beginner
1,019 Views

This topic has appeared in several posts, but I am having trouble making a slightly different implementation work and could use some help.

I have a FORTRAN simulation that must dynamically allocate a very large array of aero data.  The array is too large to statically dimension.  This array is defined in a module and sized using the allocate statement.  I would like move this module definition into a DLL that can then be shared across multiple simulations running in parallel.  The data is read only and the simulations do not interact with each other.

From an example I found in a post, the DLL code is:

     module sharedmemory

          !dec$ attributes dllexport :: darray, dummy

          real, dimension(:), allocatable :: darray

          real :: dummy = 111.1

     end module sharedmemory

     subroutine allocatearray

          !dec$ attributes dllexport :: allocatearray

          use sharedmemory

          allocate( darray(3) )

          return

     end subroutine

 

The first process that makes the call to allocate the memory is:

     program service

          !dec$ attributes dllimport :: allocatearray

          use sharedmemory

          call allocatearray

          ! manipulate the numbers over a period of time

          stop

     end program

The second process that reads the data is:

     program reader

          use sharedmemory

          !print the numbers over a period of time

          stop

     end program

I have changed the properties of both process to use the same run-time library as the DLL, and linker has "/section:.data, RWS" added.

Both processes see the dummy variable; it is statically allocated. Service allocates the array and manipulates it with no problem.  Reader will either show garbage for the darray or throws a seg fault.  If I don't allocate the memory in Service, Reader will throw an error about the pointer not being initialized.  My guess is that, while the pointer variable darray is shared, the data it points to is actually local to the Service process.

How do I get the allocated data shared through the DLL?

 

     Thanks,

     Jim

0 Kudos
6 Replies
IanH
Honored Contributor III
1,019 Views
(The hamster powering the forum appears to have fallen off his wheel. Lets see how this goes.) As you have guessed, the memory allocated for the array will be process local. If you want to use this strategy, I think you will have to take a step closer to the operating system. See the attached two programs for example. [fortran] PROGRAM one USE IFWIN USE, INTRINSIC :: ISO_C_BINDING, ONLY: & C_PTR, C_SIZEOF, C_F_POINTER, C_NULL_PTR, C_ASSOCIATED IMPLICIT NONE INTEGER, PARAMETER :: rk = KIND(1.0) INTEGER, PARAMETER :: data_size = 100 CHARACTER(*), PARAMETER :: mapping_name = 'I_like_Fortran' INTEGER(HANDLE) :: file_mapping TYPE(C_PTR) :: ptr REAL(rk), POINTER :: data(:) INTEGER :: i file_mapping = CreateFileMapping( & INVALID_HANDLE_VALUE, & ! Page file please. NULL, & ! security descriptor PAGE_READWRITE, & 0, & ! Top word of size. INT(data_size * C_SIZEOF(1.0_rk), DWORD), & mapping_name // ACHAR(0) ) IF (file_mapping == 0) THEN ERROR STOP 'No map for me today :(' END IF ptr = TRANSFER(MapViewOfFile( & file_mapping, & FILE_MAP_WRITE, & 0_DWORD, & 0_DWORD, & 0_DWORD ), C_NULL_PTR) IF (.NOT. C_ASSOCIATED(ptr)) THEN ERROR STOP 'MapViewOfFile not happy :(' END IF CALL C_F_POINTER(ptr, data, [data_size]) FORALL (i = 1:data_size) data(i) = i PRINT "('Now start process two, press enter when done.')" READ "()" END PROGRAM one PROGRAM two USE IFWIN USE, INTRINSIC :: ISO_C_BINDING, ONLY: & C_PTR, C_F_POINTER, C_NULL_PTR, C_ASSOCIATED IMPLICIT NONE INTEGER, PARAMETER :: rk = KIND(1.0) INTEGER, PARAMETER :: data_size = 100 CHARACTER(*), PARAMETER :: mapping_name = 'I_like_Fortran' INTEGER(HANDLE) :: file_mapping TYPE(C_PTR) :: ptr REAL(rk), POINTER :: data(:) file_mapping = OpenFileMapping( & FILE_MAP_READ, & FALSE, & mapping_name // ACHAR(0) ) IF (file_mapping == 0) THEN ERROR STOP 'You forgot to start one.exe' END IF ptr = TRANSFER(MapViewOfFile( & file_mapping, & FILE_MAP_READ, & 0_DWORD, & 0_DWORD, & 0_DWORD ), C_NULL_PTR) IF (.NOT. C_ASSOCIATED(ptr)) THEN ERROR STOP 'MapViewOfFile not happy :(' END IF CALL C_F_POINTER(ptr, data, [data_size]) PRINT "(*(G0,:,', '))", data END PROGRAM two [/fortran] [plain] >ifort /check:all /warn:all /standard-semantics "2015-09-09 one.f90" && "2015-09-09 one.exe" Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 16.0 Build 20150815 Copyright (C) 1985-2015 Intel Corporation. All rights reserved. Microsoft (R) Incremental Linker Version 10.00.40219.01 Copyright (C) Microsoft Corporation. All rights reserved. "-out:2015-09-09 one.exe" -subsystem:console "2015-09-09 one.obj" Now start process two, press enter when done. (in a different command prompt) >ifort /check:all /warn:all /standard-semantics "2015-09-09 two.f90" && "2015-09-09 two.exe" ... 1.000000, 2.000000, 3.000000, 4.000000, 5.000000, 6.000000, 7.000000, 8.000000, 9.000000, 10.00000, 11.00000, 12.00000, 13.00000, 14.00000, 15.00000, 16.00000, 17.00000, 18.00000, 19.00000, 20.00000, 21.00000, 22.00000, 23.00000, 24.00000, 25.00000, 26.00000, 27.00000, 28.00000, 29.00000, 30.00000, 31.00000, 32.00000, 33.00000, 34.00000, 35.00000, 36.00000, 37.00000, 38.00000, 39.00000, 40.00000, 41.00000, 42.00000, 43.00000, 44.00000, 45.00000, 46.00000, 47.00000, 48.00000, 49.00000, 50.00000, 51.00000, 52.00000, 53.00000, 54.00000, 55.00000, 56.00000, 57.00000, 58.00000, 59.00000, 60.00000, 61.00000, 62.00000, 63.00000, 64.00000, 65.00000, 66.00000, 67.00000, 68.00000, 69.00000, 70.00000, 71.00000, 72.00000, 73.00000, 74.00000, 75.00000, 76.00000, 77.00000, 78.00000, 79.00000, 80.00000, 81.00000, 82.00000, 83.00000, 84.00000, 85.00000, 86.00000, 87.00000, 88.00000, 89.00000, 90.00000, 91.00000, 92.00000, 93.00000, 94.00000, 95.00000, 96.00000, 97.00000, 98.00000, 99.00000, 100.0000 [/plain]
0 Kudos
andrew_4619
Honored Contributor III
1,019 Views

I think you need to tidy up when you are done....

"Mapped views of a file mapping object maintain internal references to the object, and a file mapping object does not close until all references to it are released. Therefore, to fully close a file mapping object, an application must unmap all mapped views of the file mapping object by calling UnmapViewOfFile and close the file mapping object handle by calling CloseHandle. These functions can be called in any order."

https://msdn.microsoft.com/en-gb/library/windows/desktop/aa366537%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396

 

0 Kudos
IanH
Honored Contributor III
1,019 Views

That's probably good practice in case the structure of the program changes, but that clean-up will happen anyway when the process terminates.

0 Kudos
James_S_8
Beginner
1,019 Views

Thanks for the replies.  I am heading down to the lab to give it a try.  The code base for this simulation is very large, and I am trying to implement a solution that integrates with this base and doesn't require a lot of changes.  The aero data array is already defined in a module and dynamically allocated.  The path I went down seemed to offer a solution that had no code impact below the definition and allocation; except I couldn't allocate the memory across processes!

0 Kudos
James_S_8
Beginner
1,019 Views

Thanks for the code ... I have it running in our lab.  I have tripped over something else though.  I am trying to put the code to set up shared memory in a subroutine, and have created an include file containing the definitions for rk and data.  The subroutine is able to create the shared memory and it can manipulate the data array.  Once control returns to the program, data is still seen as an undimensioned array and an error gets thrown.  The program does have the include file.

I am not understanding something.

 

0 Kudos
James_S_8
Beginner
1,019 Views

Scratch that last question ... as you might have guessed FORTRAN is not my principle programming language.

0 Kudos
Reply