Binding OpenMP C function

Hello everyone !

I know how to call c function with rust. However I'm interesting by use multithreaded library written in C and I need your help. Suppose I want to call the following function (which use OpenMP):

double parallel()
{
    int const n = 1000;

    double A[n][n];
    double B[n][n];
    double P[n][n];

    int i, j, k;

    double somme;

    for (i = 0; i<n; i++)
    {
        for (j = 0; j<n; j++)
        {
            A[i][j] = 1.0/(i*j +1 );
            B[i][j] = 1.0/(i*j +1);
        }
    }

    #pragma omp parallel for
    for (i = 0; i<n; i++)
    {
        for (j = 0; j<n; j++)
        {
            somme = 0.0;

            for (k = 0; k<n; k++)
            {
                somme = somme + A[i][k]*B[k][j];
            }

            P[i][j] = somme;
        }
    }

    return P[n-1][n-1];
}

So I need the following rust code (for example) :

extern crate libc;
use libc::c_double;

#[link(name = "mylib")]
extern "C" {
    fn parallel() -> c_double;
}

fn main() {
    unsafe {
        println!("{}", parallel());
    }
}

So I build my C function :

gcc -c ./src_c/* -fopenmp 
ar rcs libmylib.a *.o

And finally :

RUSTFLAGS='-L .' cargo run 

If I remove the flag -fopenmp (or the line #pragma omp parallel for and this flag) this work. But in this situation I have a problem with the parallel features. rustc message :

parallel.c:(.text+0x505) : undefined reference to « GOMP_parallel »

How can I call my function without error ?

Thank you !

C compilers automagically add OpenMP runtime libraries when you use -fopenmp flag, but Rust doesn't know you use OpenMP, or that OpenMP even exists, so it doesn't add the GOMP libraries for you.

I've created openmp-sys for that.

Alternatively, you could try rewriting the C function into Rust and parallelize it using rayon. Rayon is quite fast and similar in capabilities to OpenMP. Just keep in mind that in Rust [i] can be quite slow. For C-like performance you need to use either Iterators or .get_unchecked(i).

2 Likes

Thank you very much for your solution. But I don't understand what change I need to do in my codes... Is it :

OPENMP_STATIC=1 RUSTFLAGS='-L .' cargo run 

?

That don't work... Your documentation is difficult to understand for me... Can you precise ?

In addition, this is just an example, not a C function that I really need ! :wink:

You haven't described what doesn't work. Does the openmp-sys crate print any warnings? Try cargo build --verbose and see if correct libraries are passed to the linker.

BTW, you can use the cc crate to compile the C project in build.rs, so that you don't have to manually invoke ar, set RUSTFLAGS, etc.

I'm sorry, in fact I didn't understand how to use openmp-sys ^^'

I found solution : Add this line in main.rs

#[link(name = "gomp")]

And that compile and run multithreaded operations.

So your crate is designed to be used with cc crate, right ?

openmp-sys does not require cc. It's designed to work around problems that #[link(name = "gomp")] creates, such as link errors with gcc installations that put libgomp in a private directory, as well as work around portability issues, because gomp is GCC-only.

I don't know why it's not working for you. You haven't elaborated beyond "don't work".

Maybe try adding:

extern crate openmp_sys;

to your project.

So if I need to publish my code I will look your crate better. Thank you !

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.