I have a main program, written in C, that utilizes a threadpool of 12 threads (using pthreads)to perform parallel processing of some science data. Our group has a legacy Fortran subroutine that we need to call from each of thread to do the actual processing on a subset of the data. What are some basic guidelines for converting this Fortran subroutine so that it is thread safe?
I'm getting run-time errors in the Fortran code (forrtl severe 29). The subroutine reads/writes to several thread-specific files and allocates/deallocates memory structures. I'm fluent in C/C++ but a novice in Fortran. It seems as though the Fortran subroutine is not creating thread-specific local memory or io units?
I'm usingifortv11.1 to compile the Fortran code and gcc v4.1.2 to compile and link the program in Linux.
correct, IO units are a process-wide shared table. So each thread will need a unique IO unit. You'll need to coordinate the threads so they don't reuse the same unit number. And like in C, if you have unique file pointers BUT they point to the same file, you'll have to synchronize or coordinate the accesses. Unique IO units to unique files. I've always used an array of unit numbers indexed by the thread logical number ( base 1 for Fortran ).
Avoid the -SAVE compiler option and SAVE attribute. Avoid COMMON blocks. Avoid writing to variables in MODULEs : all of these are shared
Do not use the -heap-arrays compiler option
local variables declared within the subroutines/functions will be thread-local as long as you don't see SAVE or compile with -save.
Declare the functions and subroutines with the prefix RECURSIVE.
RECURSIVE INTEGER FUNCTION FEE(...
The default for function/subroutine declared "local" arrays are SAVE. RECURSIVE defaults "local" arrays to stack. (In this case RECURSIVE means REENTRANT - FORTRAN does not have a REENTRANT function/subroutine attribute.)
As Jim said, RECURSIVE declaration assures that local arrays and variables are on stack, consistent with threading. Without that declaration, you would depend on setting -auto, or other options which imply it, including -openmp or -reentrant. Yes, there is an ifort option -reentrant, although it's not a Fortran declaration. With such options set, you must take care to avoid uninitialized variables (which in any case aren't compatible with threading).