Introduction
Java is powerful platform for rapid software development with open source frameworks(spring, apache camel, apache hadoop, jclouds), different data sources (http, soap, rest, smtp, scp, jms, CORBA, relational/NoSQL databases etc) and a huge community of developers. OpenCL is portable language and API for heterogeneous parallel computation on GPU and many core CPU. It's great to join these cross-platform technologies together!The following information is about debugging OpenCL kernel invocation from java program on Ubuntu Linux for AMD implementation.
Hardware: x86 SSE3 capable CPU
OS environment: Ubuntu 11.04 + AMD Accelerated Parallel Processing
Software: IntelliJ Idea or any other java IDE, GNU Project Debugger(gdb), Data Display Debugger (ddd)
Java libraries: javacl ...
First you need to install the latest stable AMD Accelerated Parallel Processing, create a java project with javaCL binding library dependency, write openCL kernels and invoke it from java code ;) You can try debug demos from http://code.google.com/p/javacl/wiki/SamplesAndDemos to quick start
JavaCL is an excellent OOP java library for OpenCL with clear documentation. JavaCL is available as maven2 artifacts: http://code.google.com/p/nativelibs4java/wiki/Maven
So let me use openCL code form http://stackoverflow.com/a/5495666
Debug OpenCL kernel on CPU
Attention! AMD OpenCL CPU implementation(APP SDK 2.4) don't skip writing out of texture bound in contrast with GPU implementation, but pixel reading are emulated correctly. So please check pixel coordinates before writing in each write_imagef function
For debugging purposes we need to run kernel on CPU (instead of GPU)
List<CLPlatform.DeviceFeature> features =
Arrays.asList(CLPlatform.DeviceFeature.CPU);
for (CLPlatform platform : JavaCL.listPlatforms()) {
List<CLDevice> devices = Arrays.asList(platform.listAllDevices(true));
device=CLPlatform.getBestDevice(features, devices);
}
Compile OpenCL kernel with -g and -O0 options:
private static KernelItem createKernel(String kernelResource, CLContext context) throws IOException, CLBuildException {With latest version of javaCL use JAVACL_DEBUG=1 (or the equivalent Java property javacl.debug=true) to achieve compiling kernel with debug information without optimization. Thanks Oliver for quick support!
String kernelSrc = IOUtils.toString(Wavelet.class.getResourceAsStream(kernelResource));
if(kernelSrc==null){
throw new IllegalArgumentException("Resource "+kernelResource+" not found in classpath");
}
CLProgram program = context.createProgram(kernelSrc);
program.addBuildOption("-g");
program.addBuildOption("-O0");
CLKernel[] kernels = program.createKernels();
if (kernels.length == 0){
throw new RuntimeException("No kernels found in the source code "+kernelResource
+" ! (please mark a function with __kernel)");
} else {
if (kernels.length > 1)
throw new RuntimeException("Too many kernels found in the source code ! Expected one kernel function");
}
return new KernelItem(program,kernels[0]);
}
Use this code snippet to print on console command for debugging the current java process (for latest javaCL just read program log in debug mode)
String mxBeanName = ManagementFactory.getRuntimeMXBean().getName();
String pid = mxBeanName.substring(0, mxBeanName.indexOf("@"));When our kernel code compiled and available to run by javacl host code we can freeze a java program in breakpoint:
System.out.println("sudo gdb --tui --pid=" + pid);
System.out.println("sudo ddd --debugger \"gdb --pid=" + pid + "\"");
Command "echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope" let you to start debugger as unprivileged user without "sudo".
Open terminal and attach to running JVM using command like:
sudo ddd --debugger "gdb --pid=14276"
You can list all available for ddd openCL kernel with debugging symbols:
info funct __OpenCL
After that you need execute command:
list __OpenCL_bicubicUpscale_kernelto display source of "bicubicUpscale" kernel.
Now you can set breakpoint visually in source code.
Don't forget to continue an execution of your program with gdb command: continue
We can see a variable value in ddd, we can use step command and other powerful debugging techincs when the java program invoke "bicubicUpscale"
If you like console gdb use command: sudo gdb --tui --pid=14276
Debug OpenCL kernel on GPU
Also you can watch internal OpenCL kernel data on GPU. To achieve it you need add in kernel preprocessor directive
#pragma OPENCL EXTENSION cl_amd_printf : enableand use printf functionality inside kernel
Conclusion
Do you think that it's too complicated to create OpenCL programms on linux?))) I am still waiting for free and easy to use development tools for linux...
If AMD will release fast APU fusion x86 processors with Graphics Core Next (GCN), Radeon HD 7000 GPU, implements zero-copy for APU on openCL Linux drivers and improved development tools for Linux and java developers, we can develop powerful cross-platform application for hardware architecture of future.
This is my own opinion)
Links
- OpenCL bindings for Java: http://code.google.com/p/javacl/
- AMD Accelerated Parallel Processing (APP) SDK: http://developer.amd.com/sdks/amdappsdk/pages/default.aspx
- Debugging Applications for AMD OpenCL platform: http://developer.amd.com/zones/OpenCLZone/programming/pages/debuggingopenclapps.aspx
- Debugging opencl program with gdb: http:/samritmaity.wordpress.com/2009/11/20/debugging-opencl-program-with-gdb
- Basic GDB commands: http://www.cs.mcgill.ca/~consult/info/gdb.html
- DDD manual: http://www.gnu.org/s/ddd/manual/html_mono/ddd.html
- Debugging with GDB manual: http://www.gnu.org/s/gdb/documentation/
- GNU GDB Debugger Command Cheat Sheet: http://www.yolinux.com/TUTORIALS/GDB-Commands.html