пятница, 2 декабря 2011 г.

OpenCL kernel debugging for java host code

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 {
        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]);
    }
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!

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("@"));
System.out.println("sudo gdb --tui --pid=" + pid);
System.out.println("sudo ddd --debugger \"gdb --pid=" + pid + "\"");
When our kernel code compiled and available to run by javacl host code we can freeze a java program in breakpoint:



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_kernel
to 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 : enable
and 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



Trademarks

The names and trademarks of companies, products and services are the property of their respective owners.