Here is a step by step instruction of compiling cuda code through JNI interface.
- Declared a simple native method, and called System.loadLibrary in java
package com.name.package.jniexample;
public class HelloJNI {
static {
try{
System.loadLibrary("hello");
}
catch(UnsatisfiedLinkError e){
System.err.println("Cannot load .so library.")
e.toString();
}
}
private native void sayHello(String str);
public static void main(String[] args) {
new HelloJNI().sayHello();
}
}
- Compile the java file, create header file
javac $(dir)/HelloJNI.java
javah com.name.package.jniexample
Notice that the directory of calling “javac” should be exactly one level out of the directory which contains the package. Otherwise, an error “Error: Could not find class file for ‘HelloJNI’” will be popped out.
Now a .h file named “com_name_package_HelloJNI.h” will be generated like below.
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class gpumcse_src_cexample_HelloJNI */
#ifndef _Included_com_name_package_HelloJNI
#define _Included_com_name_package_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: gpumcse_src_cexample_HelloJNI
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_name_package_HelloJNI_sayHello
(JNIEnv *, jobject, jstring str);
#ifdef __cplusplus
}
#endif
#endif
- Include the header file in the cuda code, implemente the cuda algorithm
#include <jni.h> // JNI header provided by JDK
#include <stdio.h> // C Standard IO Header
#include "com_name_package_HelloJNI.h" // Generated
#include <iostream>
#include <fstream>
// Implementation of the native method sayHello()
JNIEXPORT void JNICALL Java_com_name_package_HelloJNI_sayHello(JNIEnv *env, jobject thisObj, jstring str) {
const jbyte *str=(const jbyte *)env->GetStringUTFChars(str, JNI_FALSE);
printf("Hello, %s.\n", str);
env->ReleaseStringUTFChars(str, (const char*)str);
return;
}
- compiled cuda code through nvcc, used nvcc -fPIC -o to create output fle (just like what the built in make file does) used nvcc -shared to create jnilib
sudo /usr/local/cuda-9.2/bin/nvcc -Xcompiler -fPIC -std=c++11 -I$(include_path) \
-shared -I=$(JAVA_HOME)/include -I=$(JAVA_HOME)/include/linux \
$(dir)/main.cu -o $(dir)/libhello.so
- Execute the java main function
java -Djava.library.path=/path/to/.so/file/ $(dir)/HelloJNI
Happy!