0

I'm trying to call a C function from Java. The C function parallel a for loop by using openmp. However, after the program finishes, the result shows only one thread is used. So, I'm wondering is it a feasible way to use the openmp with JNI.

Thanks

Below is my clang information and the content of makefile:

clang version 3.5.0 
Target: x86_64-apple-darwin15.0.0
Thread model: posix


CC = gcc
CLANG = clang-omp
CFLAGS = -c -Wall -fPIC -std=c11
OMP = -fopenmp
LIBFLAG = -dynamiclib
INCPATH = -I/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/include -I/usr/local/Cellar/libiomp/20150701/include/libiomp -I/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/include/darwin -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers
LIBPATH = -L./ -L/usr/local/Cellar/libiomp/20150701/lib -lepanet -liomp5
all: library

library: *.o
    $(CC) $(LIBFLAG) $(OMP) -o libJNIFitness.jnilib *.o 

*.o: *.c
    $(CC) $(OMP) $(CFLAGS) $(INCPATH) *.c

clean:
    rm *.o libJNIFitness.jnilib
Juneyee
  • 389
  • 2
  • 6
  • 15
  • Yes, I did this [cholmod-in-java](http://stackoverflow.com/questions/17046585/cholmod-in-java/30526005#30526005). – Z boson Oct 29 '15 at 07:51
  • What OS, what compiler, what compiler options did you use, what's your hardware? – Z boson Oct 29 '15 at 07:52
  • It's OSX EI Capitan so the compiler is LLVM and I use clang-omp to compile the C code. – Juneyee Oct 29 '15 at 10:59
  • What version of Clang are you using? What are your compiler options? Have you written a little hello world with openmp and clang to see that you get more than one thread? In case you have not noticed there have been several questions on SO lately about problems with Clang and OpenMP. – Z boson Oct 29 '15 at 11:31
  • @Zboson Thanks for your reply, I add the information you asked for. My test program runs well with C only. – Juneyee Oct 29 '15 at 15:16
  • You still have not made it clear if your C only program is showing multiple threads being used. Did you verify this? Note that only Clang 3.7 has built in OpenMP support so I guess you integrated OpenMP into Clang yourself? – Z boson Oct 29 '15 at 16:34

1 Answers1

0

Of course you can run OpenMP within the JNI method. Watch the following example (which includes JNI code [both Java and C-counter-side] and the Makefile). It calculates pi through an approximation using several threads and before calculating it each thread identifies itself on the screen.

You may need to adapt it changing the CC and JDK variables to your environment plus some Linux/gcc vs MacOsX/clang flags (such as changing -fPIC -DPIC into -dynamiclib, among others). Then you can run it by executing:

make run

and outputs the following

LD_LIBRARY_PATH=. JNItest
within Java_JNItest_CalculatePi
Java_JNItest_calculatepi: I'm thread 0 out of 4
Java_JNItest_calculatepi: I'm thread 2 out of 4
Java_JNItest_calculatepi: I'm thread 1 out of 4
Java_JNItest_calculatepi: I'm thread 3 out of 4
returning to Java...
In Java, the value of pi is 3.1415926535896825

File JNItest.java

public class JNItest
{
    static { System.loadLibrary("pi"); }

    public static native double CalculatePi (long nsteps);

    public static void main(String args[])
    {
        System.out.println ("In Java, the value of pi is " +
          new JNItest().CalculatePi(100_000_000));
    }
}

File pi.c

#include <stdio.h>
#include <JNItest.h>

JNIEXPORT jdouble JNICALL Java_JNItest_CalculatePi
  (JNIEnv * env, jclass jc, jlong nsteps)
{
    jdouble h, area, x;

    printf ("within Java_JNItest_CalculatePi\n");

    h = 1.0 / (jdouble) nsteps;
    area = 0.0;
    #pragma omp parallel private(x)
    {
        int i;
        printf ("Java_JNItest_calculatepi: I'm thread %d out of %d\n",
            omp_get_thread_num(), omp_get_num_threads());

        #pragma omp for reduction(+:area)
        for (i = 1; i <= nsteps; i++)
        {
            x = h * ((double)i - 0.5);
            area += (4.0 / (1.0 + x*x));
        }
    }

    printf ("returning to Java...\n");

    return h * area;
}

File makefile

all: JNItest.class libpi.so

CC=gcc
JDK=/usr/lib/jvm/java-7-openjdk-amd64

JNItest.class: JNItest.java
    $(JDK)/bin/javac JNItest.java

JNItest.h: JNItest.java
    $(JDK)/bin/javah JNItest

libpi.so: JNItest.h
    $(CC) -fopenmp -fPIC -DPIC pi.c -I. -I$(JDK)/include -shared -o libpi.so

clean:
    rm libpi.so JNItest.h JNItest.class

run: JNItest.class libpi.so
    LD_LIBRARY_PATH=$(PWD):$(LD_LIBRARY_PATH) $(JDK)/bin/java JNItest
Harald
  • 3,110
  • 1
  • 24
  • 35