GPUコンピューティングのOpenCLをJavaから使うライブラリがありました。幾つか異なるライブラリがあります。
jocl.org
- http://www.jocl.org
- ライセンス:MIT/X11 License
- 最新バージョン:0.1.4 (2010/08/18)
- OpenCL 1.1対応、
ドキュメント・サンプルは充実していそうです。
OpenCL API(C言語インタフェース)を薄くラッピングしたライブラリで、オブジェクト指向なAPIにはなっていません。定数もそのままの名称で登場します。OpenCL APIをC言語で扱っていた人向けかも。
JOCL by JogAmp.org
"Project JOCL"
- http://jogamp.org/jocl/www/
- ライセンス:Creative Commons Attribution 3.0 License
- 最新バージョン:gitリポジトリから最新ソースを入手しビルドするため、明確にバージョン番号は付いていない
- OpenCL 1.1対応
OpenGLのJavaバインディングのひとつJOGLと同じ開発サイトで公開されており、JOGLとのシームレスな統合を唄っています。
ローレベルAPIとハイレベルAPIを提供しているとあります。
Windows版については、ネイティブコード部分のコンパイルはMinGWを使用し、Visual C++は基本的にノンサポートです。
javacl
コーディングイメージ(抜粋)
jocl.org
jocl.orgのプログラミングイメージを次に示します。
cl_platform_id platforms[] = new cl_platform_id[1]; clGetPlatformIDs(platforms.length, platforms, null); cl_context_properties contextProperties = new cl_context_properties(); contextProperties.addProperty(CL_CONTEXT_PLATFORM, platforms[0]); cl_context context = clCreateContextFromType( contextProperties, CL_DEVICE_TYPE_GPU, null, null, null); CL.setExceptionsEnabled(true); long numBytes[] = new long[1]; clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, null, numBytes); int numDevices = (int) numBytes[0] / Sizeof.cl_device_id; cl_device_id devices[] = new cl_device_id[numDevices]; clGetContextInfo(context, CL_CONTEXT_DEVICES, numBytes[0], Pointer.to(devices), null); cl_command_queue commandQueue = clCreateCommandQueue(context, devices[0], 0, null); cl_mem memObjects[] = new cl_mem[3]; memObjects[0] = ... memObjects[1] = ... memObjects[2] = ... cl_program program = clCreateProgramWithSource(context, 1, new String[]{ programSource }, null, null); clBuildProgram(program, 0, null, null, null, null); cl_kernel kernel = clCreateKernel(program, "sampleKernel", null); clSetKernelArg(kernel, 0, Sizeof.cl_mem, Pointer.to(memObjects[0])); clSetKernelArg(kernel, 1, Sizeof.cl_mem, Pointer.to(memObjects[1])); clSetKernelArg(kernel, 2, Sizeof.cl_mem, Pointer.to(memObjects[2])); long global_work_size[] = new long[]{n}; long local_work_size[] = new long[]{1}; clEnqueueNDRangeKernel(commandQueue, kernel, 1, null, global_work_size, local_work_size, 0, null, null); clEnqueueReadBuffer(commandQueue, memObjects[2], CL_TRUE, 0, n * Sizeof.cl_float, dst, 0, null, null);
見てのとおり、OpenCLのC言語APIを見るかのようなコードです。Javaプログラマーとしては、めまいがしてしまいそうです。
JOCL by JogAmp.org
チュートリアルから抜き出したプログラミングイメージ。
CLContext context = CLContext.create(); CLProgram program = context.createProgram( HelloJOCL.class.getResourceAsStream("VectorAdd.cl") ).build(); CLBuffer<FloatBuffer> clBufferA = context.createFloatBuffer(globalWorkSize, READ_ONLY); CLBuffer<FloatBuffer> clBufferB = context.createFloatBuffer(globalWorkSize, READ_ONLY); CLBuffer<FloatBuffer> clBufferC = context.createFloatBuffer(globalWorkSize, WRITE_ONLY); fillBuffer(clBufferA.getBuffer(), 12345); fillBuffer(clBufferB.getBuffer(), 67890); CLKernel kernel = program.createCLKernel("VectorAdd"); kernel.putArgs(clBufferA, clBufferB, clBufferC).putArg(elementCount); CLCommandQueue queue = context.getMaxFlopsDevice().createCommandQueue(); queue.putWriteBuffer(clBufferA, false) .putWriteBuffer(clBufferB, false) .put1DRangeKernel(kernel, 0, globalWorkSize, localWorkSize) .putReadBuffer(clBufferC, true);
javacl
javaclのプログラミングイメージを次に示します。
CLContext context = JavaCL.createBestContext(); CLQueue queue = context.createDefaultQueue(); CLKernel kernel = context.createProgram(source).createKernel("addFloats"); CLFloatBuffer aBuf = ... CLFloatBuffer bBuf = ... CLFloatBuffer outBuf = ... kernel.setArgs(aBuf, bBuf, outBuf); kernel.enqueueNDRange(queue, new int[]{n}, new int[]{1}); queue.finish();
オブジェクト指向っぽく抽象度の高いAPIとなっています。コンテクストとキューを生成し、ソースコード文字列からカーネールを生成してキューに投入という流れです。簡潔に記述できるAPIです。
JogAmp.orgのJOCLビルドは頓挫中
まず、joclのビルドには、glugenが必要。glugenを入手した後、ビルドするのですが、antのビルド設定をいろいろ調整しないとだめなようです。
BUILD FAILED .略.\build.xml:29: taskdef class com.sun.gluegen.ant.GlueGenTask cannot be found using the classloader AntClassLoader[.略.\gluegen\make\lib\antlr.jar]
また、Cのコードをビルドするのもantから行うようですが、コンパイラの指定方法等の調査・設定が必要ですが、未調査。