Skip to content

vcl #

V Computing Language

VCL is a high level way of writing programs with OpenCL using V. These are highly opinionated OpenCL bindings for V. It tries to make GPU computing easy, with some sugar abstraction, V's concurrency and channels.

![][sierpinski_triangle]![][mandelbrot_blue_red_black]![][julia]![][mandelbrot_basic]
![][mandelbrot_pseudo_random_colors]![][sierpinski_triangle2]![][julia_set]![][julia_basic]

Using custom OpenCL headers

IMPORTANT: Using a different OpenCL header version than the one used by the OpenCL library > can cause problems. If you are using a custom OpenCL header, make sure that it is > compatible with the OpenCL library you are using. > > NOTE: Darwin systems will look for the header file at <OpenCL/opencl.h> while any other > systems will look for the header file at <CL/cl.h>.

By default VCL uses the OpenCL headers from the system path and all the known locations for OpenCL headers (like /usr/include and /usr/local/include) and load the first header it finds. If you want to use a specific OpenCL header, you can add the -I flag into your V program with the path to the headers directory.

#

or at compile time:

v -I/custom/path/to/opencl/headers my_program.v

You can also link or move the headers directory into VCL's source directory. For example:

##ln -s /custom/path/to/opencl/headers ~/.vmodules/vcl/OpenCL

##ln -s /custom/path/to/opencl/headers ~/.vmodules/vcl/CL

or, you can copy the headers directory into VCL's source directory. For example you can clone the OpenCL-Headers repository and copy the headers as follows:

git clone https://github.com/KhronosGroup/OpenCL-Headers /tmp/OpenCL-Headers

##cp -r /tmp/OpenCL-Headers/CL ~/.vmodules/vcl/OpenCL

##cp -r /tmp/OpenCL-Headers/CL ~/.vmodules/vcl/CL

Loading OpenCL dynamically

By default VCL uses OpenCL loading the library statically. If you want to use OpenCL dynamically, you can use the -d vsl_vcl_dlopencl flag.

By default it will look for the OpenCL library in the system path and all the known locations for OpenCL libraries (like /usr/lib and /usr/local/lib) and load the first library it finds. If you want to use a specific OpenCL library, you can declare the environment variable VCL_LIBOPENCL_PATH with the path to the library. Multiple paths can be separated by :.

For example, if you want to use the OpenCL library from the NVIDIA CUDA Toolkit, you can do the following:

export VCL_LIBOPENCL_PATH=/usr/local/cuda/lib64/libOpenCL.so

[sierpinski_triangle]: https://raw.githubusercontent.com/vlang/vsl/main/vcl/static/sierpinski_triangle.png [mandelbrot_blue_red_black]: https://raw.githubusercontent.com/vlang/vsl/main/vcl/static/mandelbrot_blue_red_black.png [julia]: https://raw.githubusercontent.com/vlang/vsl/main/vcl/static/julia.png [mandelbrot_basic]: https://raw.githubusercontent.com/vlang/vsl/main/vcl/static/mandelbrot_basic.png [mandelbrot_pseudo_random_colors]: https://raw.githubusercontent.com/vlang/vsl/main/vcl/static/mandelbrot_pseudo_random_colors.png [sierpinski_triangle2]: https://raw.githubusercontent.com/vlang/vsl/main/vcl/static/sierpinski_triangle2.png [julia_set]: https://raw.githubusercontent.com/vlang/vsl/main/vcl/static/julia_set.png [julia_basic]: https://raw.githubusercontent.com/vlang/vsl/main/vcl/static/julia_basic.png

fn error_from_code #

fn error_from_code(code int) IError

fn error_or_default #

fn error_or_default[T](code int, default T) !T

fn get_default_device #

fn get_default_device() !&Device

get_default_device ...

fn get_devices #

fn get_devices(device_type DeviceType) ![]&Device

get_devices returns all devices of all platforms with specified type

fn panic_on_error #

fn panic_on_error(code int)

fn typed_error #

fn typed_error[T](code int) !T

fn vcl_error #

fn vcl_error(code int) !

interface ArgumentType #

interface ArgumentType {}

interface IImage #

interface IImage {
	width       int
	height      int
	nr_channels int
	data        voidptr
}

IImage holds the fileds and data needed to represent a bitmap/pixel based image in memory.

type ErrVCL #

type ErrVCL = int

ErrVCL converts that OpenCL error code to an V error

fn (ErrVCL) err #

fn (e ErrVCL) err() IError

fn (Vector[T]) length #

fn (v &Vector[T]) length() int

Length the length of the vector

fn (Vector[T]) release #

fn (v &Vector[T]) release() !

Release releases the buffer on the device

fn (Vector[T]) load #

fn (mut v Vector[T]) load(data []T) chan IError

load copies the T data from host data to device buffer it's a non-blocking call, channel will return an error or nil if the data transfer is complete

fn (Vector[T]) data #

fn (v &Vector[T]) data() ![]T

data gets T data from device, it's a blocking call

fn (Vector[T]) map #

fn (v &Vector[T]) map(k &Kernel) chan IError

map applies an map kernel on all elements of the vector

fn (Vector[T]) buffer #

fn (v &Vector[T]) buffer() &Buffer

buffer returns the underlying buffer

enum DeviceType #

enum DeviceType as i64 {
	// device types - bitfield
	cpu         = (1 << 0)
	gpu         = (1 << 1)
	accelerator = (1 << 2)
	all         = 0xFFFFFFFF
}

enum ImageChannelDataType #

enum ImageChannelDataType {
	unorm_int8 = C.CL_UNORM_INT8
}

ImageChannelDataType describes the size of the channel data type

enum ImageChannelOrder #

enum ImageChannelOrder {
	intensity = C.CL_INTENSITY
	rgba      = C.CL_RGBA
}

ImageChannelOrder represents available image types

struct Bytes #

struct Bytes {
	buf &Buffer = unsafe { nil }
}

Bytes is a memory buffer on the device that holds []byte

fn (Bytes) size #

fn (b &Bytes) size() int

size the size of the bytes buffer

fn (Bytes) release #

fn (b &Bytes) release() !

release releases the buffer on the device

fn (Bytes) load #

fn (b &Bytes) load(data []byte) chan IError

load copies the data from host data to device buffer it's a non-blocking call, channel will return an error or nil if the data transfer is complete

fn (Bytes) data #

fn (b &Bytes) data() ![]u8

data gets data from device, it's a blocking call

fn (Bytes) map #

fn (b &Bytes) map(mut k Kernel) chan IError

map applies an map kernel on all elements of the buffer

fn (Bytes) buffer #

fn (b &Bytes) buffer() &Buffer

buffer returns the underlying buffer

struct Device #

@[heap]
struct Device {
mut:
	id       ClDeviceId
	ctx      ClContext
	queue    ClCommandQueue
	programs []ClProgram
}

Device the only needed entrence for the VCL represents the device on which memory can be allocated and kernels run it abstracts away all the complexity of contexts/platforms/queues

fn (Device) add_program #

fn (mut d Device) add_program(source string) !

add_program copiles program source if an error occurs in building the program the add_program will panic

fn (Device) bytes #

fn (d &Device) bytes(size int) !&Bytes

bytes allocates new memory buffer with specified size on device

fn (Device) driver_version #

fn (d &Device) driver_version() !string

driver_version device info - driver version

fn (Device) extensions #

fn (d &Device) extensions() !string

extensions device info - extensions

fn (Device) from_image_2d #

fn (d &Device) from_image_2d(img IImage) !&Image

from_image_2d creates new Image and copies data from Image

fn (Device) image_2d #

fn (d &Device) image_2d(@type ImageChannelOrder, bounds Rect) !&Image

image_2d allocates an image buffer

fn (Device) kernel #

fn (d &Device) kernel(name string) !&Kernel

kernel returns a kernel if retrieving the kernel didn't complete the function will return an error

fn (Device) name #

fn (d &Device) name() !string

name device info - name

fn (Device) open_clc_version #

fn (d &Device) open_clc_version() !string

open_clc_version device info - OpenCL C version

fn (Device) profile #

fn (d &Device) profile() !string

profile device info - profile

fn (Device) release #

fn (mut d Device) release() !

release releases the device

fn (Device) str #

fn (d &Device) str() string

fn (Device) vector #

fn (d &Device) vector[T](length int) !&Vector[T]

vector allocates new vector buffer with specified length

fn (Device) vendor #

fn (d &Device) vendor() !string

vendor device info - vendor

fn (Device) version #

fn (d &Device) version() !string

version device info - version

struct Image #

struct Image {
	format   ClImageFormat
	desc     &ClImageDesc = unsafe { nil }
	img_data voidptr
mut:
	buf &Buffer
pub:
	@type  ImageChannelOrder
	bounds Rect
}

Image memory buffer on the device with image data

fn (Image) release #

fn (mut img Image) release() !

release releases the buffer on the device

fn (Image) data_2d #

fn (image &Image) data_2d() ![]u8

struct Kernel #

struct Kernel {
	d &Device = unsafe { nil }
	k ClKernel
}

Kernel represent a single kernel

fn (Kernel) global #

fn (k &Kernel) global(global_work_sizes ...int) KernelWithGlobal

global returns an kernel with global size set

struct KernelCall #

struct KernelCall {
	kernel            &Kernel = unsafe { nil }
	global_work_sizes []int
	local_work_sizes  []int
}

KernelCall is a kernel with global and local work sizes set and it's ready to be run

fn (KernelCall) run #

fn (kc KernelCall) run(args ...ArgumentType) chan IError

run calls the kernel on its device with specified global and local work sizes and arguments it's a non-blocking call, so it returns a channel that will send an error value when the kernel is done or nil if the call was successful

struct KernelWithGlobal #

struct KernelWithGlobal {
	kernel            &Kernel = unsafe { nil }
	global_work_sizes []int
}

KernelWithGlobal is a kernel with the global size set to run the kernel it must also set the local size

fn (KernelWithGlobal) local #

fn (kg KernelWithGlobal) local(local_work_sizes ...int) KernelCall

local ets the local work sizes and returns an KernelCall which takes kernel arguments and runs the kernel

struct Rect #

@[params]
struct Rect {
pub: // pixel need integers
	x      f32
	y      f32
	width  f32
	height f32
}

Rect is a struct that represents a rectangle shape

struct UnsupportedArgumentTypeError #

struct UnsupportedArgumentTypeError {
	Error
pub:
	index int
	value ArgumentType
}

fn (UnsupportedArgumentTypeError) msg #

fn (err UnsupportedArgumentTypeError) msg() string

struct Vector #

struct Vector[T] {
mut:
	buf &Buffer = unsafe { nil }
}

Vector is a memory buffer on device that holds []T