hadoop通过JNI调用cuda程序

一、通过JNI,将C写成的cuda编译成动态链接库

1、 写一个java类,类中包含一个native的函数,导入.so动态链接库,注意,linux中,SiftGPU其实指的是libSiftGPU.so。

package nfs.sil.image.sift.main;
import java.util.List;
import java.lang.reflect.*;
import java.util.ArrayList;
import net.semanticmetadata.lire.imageanalysis.sift.Feature;

public class FeatureExtractSIFT_GPU 
{
	static{
		try{
			System.loadLibrary("SiftGPU");
		}
		catch(UnsatisfiedLinkError e){
			System.err.println("Cannot load SIFT library\n"+e.toString());
		}
	}
	
	public FeatureExtractSIFT_GPU(){
	//	features = new ArrayList();
	}
	
	public native void ExtractSIFT(String filename, List features) throws Exception; 
	public native void ExtractSIFT(float[] data, int width, int height, List feature) throws Exception;
	
	public List ExtractFeatures(float[] data, int width, int height){
		List features = new ArrayList();
		List result = new ArrayList();
		
		try{
			ExtractSIFT(data, width, height, features);
		}catch (Exception e){
			e.printStackTrace();
			return null;
		}
		
		for(int i = 0; i < features.size(); ++i){
			float[] vec = features.get(i);
			Feature temp = new Feature();
			temp.location = new float[2];
			temp.location[0] = vec[0];
			temp.location[1] = vec[1];
			temp.scale = vec[2];
			temp.descriptor = new float[128];
			System.arraycopy(vec, 4, temp.descriptor, 0, 128);
			result.add(temp);
		}

		return result;
	}
	
	public List ExtractFeatures(String filename){
		List features = new ArrayList();
		List result = new ArrayList();
		
		try{
			ExtractSIFT(filename类, features);
		}catch (Exception e){
			e.printStackTrace();
			return null;
		}

		for(int i = 0; i < features.size(); ++i){
			float[] vec = features.get(i);
			Feature temp = new Feature();
			temp.location = new float[2];
			temp.location[0] = vec[0];
			temp.location[1] = vec[1];
			temp.scale = vec[2];
			temp.descriptor = new float[128];
			System.arraycopy(vec, 4, temp.descriptor, 0, 128);
			result.add(temp);
		}

		return result;
	}
	public static void main(String[] args){
		
		String filename = "01.png";
		System.out.println("compute 1!");
		FeatureExtractSIFT_GPU t = new FeatureExtractSIFT_GPU();
		try{
			t.ExtractFeatures(filename);
		}catch (Exception e){
			e.printStackTrace();
			return;
		}
		System.out.println("compute success!");
      
	}
}

2、javac编译这个类生成.class文件,我直接用eclipse编译了。

3、在项目目录下的./bin文件目录下,使用如下命令,生成C++函数的头文件

javah -jni -classpath . nfs.sil.image.sift.main.FeatureExtractSIFT_GPU

在该目录下会出现一个nfs_sil_image_sift_main_FeatureExtractSIFT_GPU.h的头文件,文件内容如下

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

#ifndef _Included_nfs_sil_image_sift_main_FeatureExtractSIFT_GPU
#define _Included_nfs_sil_image_sift_main_FeatureExtractSIFT_GPU
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     nfs_sil_image_sift_main_FeatureExtractSIFT_GPU
 * Method:    ExtractSIFT
 * Signature: (Ljava/lang/String;Ljava/util/List;)V
 */
JNIEXPORT void JNICALL Java_nfs_sil_image_sift_main_FeatureExtractSIFT_1GPU_ExtractSIFT__Ljava_lang_String_2Ljava_util_List_2
  (JNIEnv *, jobject, jstring, jobject);

/*
 * Class:     nfs_sil_image_sift_main_FeatureExtractSIFT_GPU
 * Method:    ExtractSIFT
 * Signature: ([FIILjava/util/List;)V
 */
JNIEXPORT void JNICALL Java_nfs_sil_image_sift_main_FeatureExtractSIFT_1GPU_ExtractSIFT___3FIILjava_util_List_2
  (JNIEnv *, jobject, jfloatArray, jint, jint, jobject);

#ifdef __cplusplus
}
#endif
#endif

4、实现nfs_sil_image_sift_main_FeatureExtractSIFT_GPU.cu,实现.h中的C++函数

5、编译,生成动态链接库

先把所有的.cu文件用nvcc编译成.o文件

最后 gcc -Wall -rdynamic 'pkg-config --cflags opencv' -fopenmp -shared -L/home/OpenCV-2.4.3/lib -lopencv_core -lopencv_highgui -L/usr/local/cuda/lib -lcudart -o libSiftGPU.so $(ALL)


二、使用hadoop运行程序

注意,在需要运行的类中包含,将一些参数分析交给GenericOptionsParser做。

GenericOptionsParser parser = new GenericOptionsParser(conf, args);
String[]otherArgs = parser.getRemainingArgs();

运行命令

hadoop jar imageRetrieval.jar nfs.sil.image.sift.index.SiftHadoopImageIndexer  -files libSiftGPU.so images index

-files意思是把libSiftGPU.so拷贝到工作机上。

另一个可行的办法是,手动将libSiftGPU.so拷贝到java.library.path所指向的文件夹下

咳咳,这种方法比较暴力~~




阅读更多
个人分类: CUDA Linux
上一篇并行计算模型
下一篇leetcode: Letter Combinations of a Phone Number
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭