(c) Wim Vanderbauwhede 2010-now
This project provides the following:
OclWrapper
: and OpenCL wrapper class in C++ with additional bindings for Fortran, C and Perl.OclBuilder.py
: a SCons builder library for OpenCL applications that useOclWrapper
ocl_env.sh
: environment variables used byOclBuilder.py
(bash syntax)
To use the OclWrapper and OclBuilder, you need the following:
- The scons build system, and therefore Python 3;
- An OpenCL SDK and an OpenCL capable device (e.g. your CPU or GPU);
- A C++ compiler and depending on your target, a C or Fortran compiler, or Perl with the
Inline::C
module.
Modify the environment variables from ocl_env.sh
to reflect your system setup and put them in your .bashrc
or .profile
or equivalent.
The environment variables defined in ocl_env.sh
are the following, you should change them to reflect the location of the SDKs on your system, the compilers used etc.:
# Path to the OpenCLIntegration folder e.g.
export OPENCL_DIR= $HOME/OpenCLIntegration
# OpenCL SDK paths
# NVIDIA
export NVSDKCUDA_ROOT="..."
# AMD
export AMDAPPSDKROOT="..."
# Intel
export INTELOCLSDKROOT="..."
# Compilers
export CXX_COMPILER=/usr/bin/g++
export CXX=$CXX_COMPILER
export C_COMPILER=/usr/bin/gcc
export CC=$C_COMPILER
# Must be either GNU or PGI compiler, no others supported yet
export FORTRAN_COMPILER=/usr/bin/gfortran
export FC=$FORTRAN_COMPILER
# Don't modify below this line
export OPENCL_GPU=`$OPENCL_DIR/bin/test_gpu.pl`
export OPENCL_CPU=`$OPENCL_DIR/bin/test_cpu.pl`
export OPENCL_ACC=`$OPENCL_DIR/bin/test_acc.pl`
export PYTHONPATH=$PYTHONPATH:$OPENCL_DIR
export PATH=$OPENCL_DIR/bin:$PATH
In the examples
folder there are a number of examples illustrating the use of OclWrapper
with C++, Fortran and Perl. See README-examples.md
in that folder for more information.
-
In your SConstruct file:
from OclBuilder import initOcl # Define your Environment as required for your build # Initialise OpenCL-specific env values env = initOcl(env) # Rest of your build as usual
-
For a simple build, you can also do:
from OclBuilder import build appname='matmult_int' # Any additional sources sources=[appname+'.cc'] build(appname,sources)
-
For building Fortran code with the OclWrapper:
from OclBuilder import initOcl, buildF envF=Environment(useF=1) envF=initOcl(envF) fsources=['matacc.f95'] buildF(envF,'mataccF',fsources)
If you use Make or another build system for the rest of your code, you can build the OclWrapper library with SCons and then use it in your build script. For example, to integrate OpenCL into Fortran, your SConscript would look like this:
from OclBuilder import initOcl
envF=Environment(useF=1)
envF=initOcl(envF)
and in your Makefile, add the following:
OCL_DIR = $(OPENCL_DIR)
OCL_OBJS = oclWrapper.o
OCL_LDFLAGS = -L/path/to/OclWrapper -L$(OCL_DIR) \
-lOclWrapperF -lOclWrapper -lOpenCL -lstdc++
In your C++ code:
#include "OclWrapper.h"
// Create a wrapper object
OclWrapper ocl(...); // see code for constructor args
ocl.makeReadBuffer(...);
ocl.makeWriteBuffer(...);
ocl.writeBuffer(...);
ocl.enqueueNDRange(cl::NDRange(...), cl::NDRange(...));
ocl.runKernel( ... ).wait();
ocl.readBuffer(...);
// There are many more options, see OclWrapper.h code
In your Fortran code:
use oclWrapper
oclMakeReadBuffer(...);
oclMakeWriteBuffer(...);
oclWriteBuffer(...);
runOcl(globalrange, localrange)
oclReadBuffer(...)
! There are many more API calls, see `oclWrapper.f95` code
In your Perl code:
use OclWrapper;
use CTypes qw(float unsigned int);
# Initialise the OpenCL system;
my $ocl = new OclWrapper('matacc.cl','mataccKernel10');
# This returns the number of cores on the device
my $nunits = $ocl->getMaxComputeUnits();
# Create the buffers
my $mA_buf = $ocl->makeReadBuffer(float, $mSize); # read from by the kernel
my $mC_buf = $ocl->makeWriteBuffer(float, $nunits); # written to by the kernel
# setArg takes the index of the argument and a value of the same type as the kernel argument;
$ocl->setArrayArg(0, $mA_buf );
$ocl->setArrayArg(1, $mC_buf);
$ocl->setConstArg(2, unsigned int, $mWidth);
# Write the array to the device
$ocl->writeArray($mA_buf,float, $mSize,$mA);
# Run the kernel
$ocl->run($nunits*16,16);
# Read back the results;
my $mC = $ocl->readArray($mC_buf,float, $nunits);
my $mCtot=0.0;
for my $i (0 .. $nunits-1) {
$mCtot=$mCtot+$mC->[$i];
}