Java与Cuda混合编程

基本上和Java与C语言混合编程(链接)相同,就是在生成动态库的编译过程不同。

首先编写一个名为Main.java的文件,内容如下:

class NativeMethod{
        public native void writefloat(int nx,int nz);
}
public class Main{
        public static void main(String[] args){
                System.loadLibrary("NativeMethod");
                NativeMethod nm = new NativeMethod();
                nm.writefloat(100,100);
          }
}

编译:

javac  Main.java 

生成两个class文件:Main.class和NativeMethod.class文件。

用JNI编译:

java -jni  NativeMethod 
(注意,给名称是native方法所在类)


生成:NativeMethod.h,内容如下:

/*  DO NOT EDIT THIS FILE - it is machine generated */
#include 
 /* Header for class NativeMethod */

#ifndef _Included_NativeMethod
#define _Included_NativeMethod
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     NativeMethod
 * Method:    writefloat
 * Signature: (II)V
 */
JNIEXPORT void JNICALL Java_NativeMethod_writefloat
  (JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif
这是自动生成的,无需手动编写,我们要用到的地方是标红函数。


编写动态库的代码:
#include "NativeMethod.h"
#include 
#include 
#include 
#include 
#include 
#include 
void check_gpu_error (const char *msg) 
{
        cudaError_t err = cudaGetLastError ();
        if (cudaSuccess != err) { 
                printf("Cuda error: %s: %s\n", msg, cudaGetErrorString (err)); 
                exit(0);   
        }
}
__global__ void fun(float *val,int nx,int nz)
{
        int id=threadIdx.x+blockDim.x*blockIdx.x;
        if(id
                val[id] = id+1;
}
JNIEXPORT void JNICALL Java_NativeMethod_writefloat
        (JNIEnv *env, jobject obj, jint nx, jint nz){
        float *v,*vv;
        char FN1[250]={"v.dat"};
        FILE *fp;
        fp=fopen(FN1,"wb");
        v=(float*)malloc(nx*nz*sizeof(float));
        cudaSetDevice(0);  //   initialize device, default device=0;
        check_gpu_error("Failed to initialize device!");
        cudaMalloc(&vv, nx*nz*sizeof(float));
        cudaMemset(vv, 0, nx*nz*sizeof(float));
        fun <<<  ( nx * nz + 511 ) / 512 , 512 >>> (vv, nx, nz);
        cudaMemcpy(v, vv, nx *nz *sizeof(float), cudaMemcpyDeviceToHost);
        fwrite(v,sizeof(float),nx* nz, fp);
        fclose(fp);
}

然后编译生成动态库:

nvcc -o libNativeMethod.so -shared -Xcompiler -fPIC NativeMethod.cu -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux

注意:生成的动态库名字以Main.java中System.loadLibrary("NativeMethod");双引号中的名字加“lib”前缀和“.so”后缀(本文例子为“libNativeMethod.so”).

然后就可以运行调用了cuda的native方法的java程序:

java  -Djava.library.path=.   Main

整体的编译shell:

javac   Main.java
javah  -jni  NativeMethod
nvcc  -o  libNativeMethod.so  -shared  -Xcompiler  -fPIC  NativeMethod.cu -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux
java  -Djava.library.path=.   Main


你可能感兴趣的:(计算机语言,高性能计算)