Computing Language Utility (CLU): An Open Source API for Rapid OpenCL* Development

Introduction

The Computing Language Utility is an Open Source, lightweight API designed to help programmers explore, learn, and rapidly prototype programs with OpenCL*. This API reduces the complexity associated with initializing OpenCL* devices, contexts, kernels and parameters, etc. while preserving the ability to drop down to the lower level OpenCL* API when programmers wants to get their hands dirty. The CLU release includes an open source implementation along with documentation and samples that demonstrate how to use CLU in real applications.

You can start using and contributing today by downloading the Computing Language Utility from Github.

Why CLU?

It can be hard to get started using OpenCL*, whether new to OpenCL or as an experienced developer experimenting with some of its more advanced features. Identifying platforms, selecting devices, creating the context, building programs, debugging, and setting kernel arguments all require tedious boilerplate code. CLU seeks to simplify the routine aspects of using OpenCL* without being a “wrapper” for the whole API or restricting access to lower-level API features.

What is CLU?

CLU capabilities fall into 2 categories:

  • A simple, C-compatible runtime API
  • An off-line header generation tool

The runtime delivers high-level APIs that implement much of the boilerplate OpenCL* initialization code required by every OpenCL* application. The off-line generator for OpenCL*-C files (.cl) produces C-compatible header files containing wrapper functions for each kernel, simplifying calling from the host. CLU developers can skip most of the tedious aspects of OpenCL* and focus on writing kernel code.

Consider using CLU like GLUT* or DXUT* - a utility library for rapidly prototyping, teaching, learning, in University or lab environments.

CLU is open source! Feedback and contributions are encouraged.

What CLU is Not

While CLU provides a number of features, its philosophy is to be simple. CLU:

  • Does not enable host and device code in the same file like CUDA* or AMP*
  • Is not a “wrapper” for OpenCL*
    • CLU directly uses OpenCL* objects
    • CLU can intermingle CLU APIs with standard OpenCL* APIs
  • Does not extend the kernel language
  • Does not incorporate a grammar or translator
  • Does not provide an intermediate representation
    • CLU is nothing like PTX* or LLVM*

How to Get Started

Download the source, samples, and documentation here:

https://github.com/Computing-Language-Utility/CLU

Install an OpenCL* 1.1 (or greater) SDK appropriate for your platform. The Intel OpenCL* SDK can be found here:

http://software.intel.com/en-us/articles/vcsource-tools-opencl-sdk/

A Microsoft* Visual Studio* solution file is provided (other build environments TBD). Try the included simple.c sample, or one of the other samples provided separately.

CLU API

The CLU runtime simplifies some aspects of using OpenCL*, without replacing the whole API or wrapping any of its underlying objects. Some commonly used APIs include:

  • cluInitialize: use this to create the default CLU context, or pass in one of your own. You can use this API to add more advanced features to your application easily, including sharing with OpenGL* (if supported by your platform)
  • cluBuildSourceFromFile: you can directly acquire a handle to an OpenCL* program object from a source file with one simple function call
  • cluEnqueue: the CLU structures and API simplify launching a kernel. Launching kernels becomes even easier by using the CLU code generator described below
  • cluRelease: tells CLU to release all the objects it has created. You can initialize then release multiple times in the same application.

CLU Offline Generator

The CLU Offline code generator takes an OpenCL-C source file and generates a separate header file containing generated functions to build the code for the devices in the CLU context and call the kernel to set the kernel arguments for you). It will parse any #include statements and roll them into the generated file so no external files will have to be loaded at runtime. The CLU generator creates 2 kinds of functions for every kernel in your source:

  1. clugCreate_YOURKERNELNAME: creates the kernel. This API only builds the source on the first call
  2. clugEnqueue_YOURKERNELNAME: sets all the kernel arguments and enqueues the kernel

Example

Let’s look at the “simple” example provided with CLU. Starting with the kernel code in simple.cl:

kernel void Simple(int param1, global int* param2)
{
param2[get_global_id(0)] = param1;
}

Use the CLU generator as a custom build step to generate simple.cl.h:

clu_generator simple.cl –o simple.cl.h

Then, the following represents a complete CLU application:

#include "simple.cl.h"

void main()
{
    int* mapped = 0;
    // initialize CLU
    cl_int status = cluInitialize(0);

    // create my buffer
    int bufferLength = 1024;
    int bufferSize = sizeof(int)*bufferLength;
    cl_mem buf = clCreateBuffer(CLU_CONTEXT, …);

    // use a generated function to enqueue my kernel
    clug_Simple s = clugGet_Simple(0);

    // use a generated function to enqueue my kernel
    clu_enqueue_params params = {0};
    params.nd_range = CLU_ND1(bufferLength);
    status = clugEnqueue_Simple(s, ¶ms, 42, buf);

    // check the results
    mapped = (int*)clEnqueueMapBuffer(CLU_DEFAULT_Q, …);
    clEnqueueUnmapMemObject(CLU_DEFAULT_Q, …);

    // shut down CLU
    cluRelease();
}

OpenGL* Sharing with CLU

CLU was designed to simplify using some of the more advanced features of OpenCL, like sharing with OpenGL* contexts. To share with OpenGL* within Windows* (if your OpenCL platform supports the OpenGL sharing extension), first create an OpenGL context as usual then:

cl_context_properties properties[] =
{ 
    CL_GL_CONTEXT_KHR, (cl_context_properties)wglGetCurrentContext(),
    CL_WGL_HDC_KHR,    (cl_context_properties)wglGetCurrentDC(),
    0 
};

clu_initialize_params params = {0};
params.default_context_props = properties;
cluInitialize(¶ms);

Any custom OpenCL* context properties may be passed in through this mechanism.

To determine if you have a device that supports sharing with OpenGL, search for the string “cl_khr_gl_sharing” in among the properties of your device:

char* supports_gl = strstr((char*)cluGetDeviceInfo(0), "cl_khr_gl_sharing");

Conclusion and Next Steps

Today, OpenCL* development gets a little bit easier.

  • CLU allows you to write your first OpenCL application in under one hour
  • CLU is an open source library developed by a cross industry collaboration
  • CLU will run across many vendors platforms today

Download CLU today at: https://github.com/Computing-Language-Utility/CLU

Legal Disclaimer

Code snippets provided in this document are for illustrative purposes only. Intel disclaims any and all implied or express warranties associated with the code snippets, and any and all use of such code snippets is at the sole discretion and exclusive risk of the user.

Intel and the Intel logo are trademarks of Intel Corporation in the U.S. and other countries.

* Other names and brands may be claimed as the property of others. * OpenCL and the OpenCL logo are trademarks of Apple Inc. used by permission by Khronos.

Para obtener información más completa sobre las optimizaciones del compilador, consulte nuestro Aviso de optimización.