oclRun: Run a kernel using OpenCL.

Description Usage Arguments Details Value Author(s) See Also Examples

View source: R/ocl.R

Description

oclRun is used to execute code that has been compiled for OpenCL.

oclResult collects results from an asynchronous oclRun call.

Usage

1
2
oclRun(kernel, size, ..., native.result = FALSE, wait = TRUE, dim = size)
oclResult(context, wait = TRUE)

Arguments

kernel

kernel object as obtained from oclSimpleKernel

size

length of the output vector

...

additional arguments passed to the kernel

native.result

logical scalar, if TRUE then the result from a single-precision kernel is not converted to double-precision but returned as a clFloat object.

wait

logical scalar, if TRUE then oclRun waits for the operation to finish and returs the result. Otherwise the kernel is only enqueued, so it will be run in parallel to R and have to be collected later with oclResult.

dim

numeric vector describing the global work dimensions, i.e., the index range that the kernel will be run on. The kernel can use get_global_id(n) to obtain the (n + 1)-th dimension index and get_global_size(n) to get the dimension. OpenCL standard supports only up to three dimensions, you can use use index vectors as arguments if more dimensions are required. Note that dim is not necessarily the dimension of the result although it can be.

context

context object that was returned by oclRun(..., wait = FALSE) call.

Details

oclRun pushes kernel arguments, executes the kernel and retrieves the result. The kernel is expected to have either __global double * or __global float * type (write-only) as the first argument which will be used for the result and const int second argument denoting the result length. All other arguments are assumed to be read-only and will be filled accoding to the ... values. Scalar values (vectors of length one) are passed as constants, vectors are passed as global objects. Only numeric (int*, double*), clFloat (float*) and logical (int*) vectors are supported as kernel arguments. Numeric (double-precision) vectors are converted to single-precision automatically when using single-precision kernel. The caller is responsible for matching the argument types according to the kernel in a way similar to .C and .Call.

oclResult retrieves the result of a previous operation that was enqueued using oclRun(..., wait = FALSE). If oclResult(..., wait = FALSE) is used then NULL is returned in case the result is not ready yet. Note that results can be collected only once and the context object becomes invalid after a successful call to oclResult since all associated OpenCL objects are released.

Value

oclRun: for wait = TRUE is the result of the operation, a numeric vector of the length size. Otherwise oclRun returns a call context object that can be used by oclResult to retrieve the result.

oclResult: Result of the previously started operation or NULL if wait=FALSE and the operation has not completed yet.

Author(s)

Simon Urbanek

See Also

oclSimpleKernel, clFloat

Examples

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
library(OpenCL)
p = oclPlatforms()
d = oclDevices(p[[1]])

code = c("
__kernel void dnorm(
  __global float* output,
 const unsigned int count,
  __global float* input,
 const float mu, const float sigma)
{
  int i = get_global_id(0);
  if(i < count)
      output[i] = exp(-0.5f * ((input[i] - mu) / sigma) * ((input[i] - mu) / sigma))
      / (sigma * sqrt( 2 * 3.14159265358979323846264338327950288 ) );
};")
k.dnorm <- oclSimpleKernel(d[[1]], "dnorm", code, "single")
f <- function(x, mu=0, sigma=1, ...)
  oclRun(k.dnorm, length(x), x, mu, sigma, ...)

## expect differences since the above uses single-precision but
## it should be close enough
f(1:10/2) - dnorm(1:10/2)

## this is optional - use floats instead of regular numeric vectors
x <- clFloat(1:10/2)
f(x, native.result=TRUE)

## does the device support double-precision?
if (any(grepl("cl_khr_fp64", oclInfo(d[[1]])$exts))) {
code = c("#pragma OPENCL EXTENSION cl_khr_fp64 : enable
__kernel void dnorm(
  __global double* output,
 const unsigned int count,
  __global double* input,
 const double mu, const double sigma)
{
  int i = get_global_id(0);
  if(i < count)
      output[i] = exp(-0.5f * ((input[i] - mu) / sigma) * ((input[i] - mu) / sigma))
      / (sigma * sqrt( 2 * 3.14159265358979323846264338327950288 ) );
};")
k.dnorm <- oclSimpleKernel(d[[1]], "dnorm", code, "double")
f <- function(x, mu=0, sigma=1)
  oclRun(k.dnorm, length(x), x, mu, sigma)

## probably not identical, but close...
f(1:10/2) - dnorm(1:10/2)
} else cat("\nSorry, your device doesn't support double-precision\n")

## Note that in practice you can use precision="best" in the first
## example which will pick "double" on devices that support it and
## "single" elsewhere

OpenCL documentation built on May 29, 2017, 8:13 p.m.