Unfortunately there is no simple answer. It depends on what you are trying to do. You need to look at the support that is provided by the compiler's you are using and make sure that you can do it without OpenMP first. There are a number of problems that you have to account for. For example:
- passing by value vs passing by reference
- external name mangaling
- data representation and layout
- link order
None of these are OpenMP specific. If you can get your program to work without OpenMP, then you should be able to get it to work with OpenMP - with some exceptions. There are a couple of things that come to mind.
First, the OpenMP spec doesn't address any inter-language compatability for the OpenMP constructs. For example, critical region names are external, but there is nothing in the OpenMP spec that says that if you use the same names for a critical region in C, C++, or Fortran that they will be the same when linked together. This is because of the name mangaling that is done by each language implementation.
Second, while the Fortran code knows it as threadprivate, the C code will only know it as data being passed (not as threadprivate).
Third, when compiling the C code you will have to make sure that you compile it with the appropriate options. The code may not have any OpenMP in it, but the OpenMP compile flag may also be doing something else that may be required (e.g., adding a compile flag for multitasking).
Fourth, when dealing with threadprivate, the OpenMP spec doesn't say when the threadprivate areas are allocated. What this means, is that you can't try and setup a pointer to the threadprivate area until you are in the parallel region.
Here is a simple example, showing it can work:
- Code: Select all
% cat lc1.f90
include "omp_lib.h"
integer :: a = 5
common /cb/ a
!$omp threadprivate(/cb/)
!$omp parallel
print *, "t#:", omp_get_thread_num(), " loc(a):", loc(a)
call func(a)
print *, "t#:", omp_get_thread_num(), " a:", a
!$omp end parallel
end
% cat lc2.c
#include <stdio.h>
void func(int *p)
{
printf("value: %i\n", *p);
*p = 10;
}
% cc -xopenmp -c lc2.c
% f90 -xopenmp -ext_names=plain lc1.f90 lc2.o
% setenv OMP_DYNAMIC FALSE
% setenv OMP_NUM_THREADS 2
% a.out
t#: 1 loc(a): -31373888
value: 5
t#: 1 a: 10
t#: 0 loc(a): 136464
value: 5
t#: 0 a: 10
This particular example is using Sun Studio, but shows some of the things I mentioned above and what you have to do for Sun Studio to work. For example:
- -xopenmp is on the C compile line even though there isn't any OpenMP in the C code
- -ext_names=plain is on the Fortran compile line to handle the name mangling differences between C and Fortran
- Fortran is used to do the linking of the two programs
You will also note, that I cheated with this example and used a very simple common block.