OPENMP + Mixing FORTRAN and C code

General OpenMP discussion

OPENMP + Mixing FORTRAN and C code

Postby digimat » Fri Apr 18, 2008 2:49 am

Dear OPENMP Experts,
I am trying to link codes complied with FORTRAN and C++ compiler builded with OPENMP pragma. To be more specific I am trying to access FORTRAN common block defined using OPENMP directive c$omp thread private /name of the common block/ in my C code. Have you ever tried this?
Linking goes fine without any error, even the executable starts fine but the common block variablle updated in c++ code does seems to be considered in the FORTRAN code. To be clear it seems like I am not accessing the same location I am novice user to OPENMP and I do not find any document talking about. You help will be really appreciated.
Thank you,
digimat
digimat
 
Posts: 9
Joined: Fri Apr 18, 2008 2:23 am

Re: OPENMP + Mixing FORTRAN and C code

Postby ejd » Fri Apr 18, 2008 6:34 am

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.
ejd
 
Posts: 1025
Joined: Wed Jan 16, 2008 7:21 am

Re: OPENMP + Mixing FORTRAN and C code

Postby digimat » Wed Apr 23, 2008 2:35 am

Hello ejd,
Thank you very much for this clear and wonderful reply. I have been working with inter-language programming for almost a year. I have the executable working without OPENMP options.
In C and C++ defining a struct as
extern "C" {
extern struct
{
float sl[n],sndsp[n],diagm[n],sarea[n];
}
sundc_;
}

Is an equivalent definition of FORTRAN common block
common/sundc/sl(n),sndsp(n),diagm(n),sarea(n)
And the linker easily finds all the symbols defined external and there is no linker error. And everything was going fine till today without OPENMP version.
As I need to build now parallel libraries. I moved to SMP version of the libraries.
The OPENMP version of the following statements are as follows. In FORTRAN
common/sundc/sl(n),sndsp(n),diagm(n),sarea(n)
c$omp thread private (/sundc/)
In C++
extern "C" {
extern struct
{
float sl[n],sndsp[n],diagm[n],sarea[n];
}
sundc_;
}

#pragma omp threadprivate(sundc_)

In my C+ code I try to update the array as sundc_.sl[i] and these update does not seem to be taken in the FORTRAN code. Do you think it is possible to access the commmon block if will compile my code with all necessary OPENMP option?
I tried to explain you what I am trying to achieve. Unfortunately I do not pass the FORTRAN common block via functions to C instead I access them directly. Can you suggest a better approach if you know?
Thank you!!!
digimat
 
Posts: 9
Joined: Fri Apr 18, 2008 2:23 am

Re: OPENMP + Mixing FORTRAN and C code

Postby ejd » Wed Apr 23, 2008 5:44 am

If you look at my little example, you will see that the location of "a" is different for each thread. With the Sun implementation if you print out the location of "a" before the parallel region you will see that the location is the same for the sequential part and for thread 0 (the master thread). This isn't necessarily the case in all implementations (and could change for the Sun implementation) because the OpenMP spec doesn't pin down when threadprivate areas are created.

The point being, that the version that is being resolved at link time, is a static version created at compile time - i.e., the version for the sequential part. If one of the threads in the parallel region "reuses" that version, then you might see the values changed for one of the threads doing it your way. However, the other copies used in the parallel region are created during execution and so they are not known by your C program. That is why the only way you might get this to work is if you pass the location of the first item in the threadprivate common block to the C program and then "overlay" your structure on top of it.

Something like this (quick and dirty example):
Code: Select all
% cat lc1.f90
  include "omp_lib.h"

  integer, parameter :: n = 5
  integer :: a(n), b(n), c(n)
  common /cb/ a, b, c
  !$omp threadprivate(/cb/)

  a = 5
  b = 0
  !$omp parallel
    print *, "t#:", omp_get_thread_num(), "  loc(a):", loc(a), "  loc(b):", loc(b)
    call func(loc(a))
    print *, "t#:", omp_get_thread_num(), "  a:", a, "  b:", b
  !$omp end parallel
  end

% cat lc2.c
#include <stdio.h>

typedef struct
{
  int a[5], b[5];
} fcb;

void func(fcb **p)
{
  (**p).a[0] = 10;
  (**p).a[3] = 15;
  (**p).b[0] = 20;
  (**p).b[1] = 25;
}

% cc -xopenmp -c lc2.c
% f90 -xopenmp -ext_names=plain lc1.f90 lc2.o
% a.out
t#: 0   loc(a): 136680   loc(b): 136700
t#: 0   a: 10 5 5 15 5   b: 20 25 0 0 0
t#: 1   loc(a): -31373888   loc(b): -31373868
t#: 1   a: 10 0 0 15 0   b: 20 25 0 0 0
ejd
 
Posts: 1025
Joined: Wed Jan 16, 2008 7:21 am

Re: OPENMP + Mixing FORTRAN and C code

Postby digimat » Thu Apr 24, 2008 8:14 am

Thank you for the advice!!!
digimat
 
Posts: 9
Joined: Fri Apr 18, 2008 2:23 am


Return to Using OpenMP

Who is online

Users browsing this forum: No registered users and 3 guests