library(OpenCL) # identify platforms on computer p <- oclPlatforms() # identify devices associated with one of the platforms d <- oclDevices(p[[1]]) # get information about the platform oclInfo(p[[1]]) # get information about the device oclInfo(d[[1]]) # set up to run Open CL code on the device # define the code as an Open CL kernel in a character string 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 ) ); };") # compile the code k.dnorm <- oclSimpleKernel(d[[1]], "dnorm", code, "single") # define an R function to send arguments to the OpenCL kernel and call it f <- function(x, mu=0, sigma=1, ...) oclRun(k.dnorm, length(x), x, mu, sigma, ...) # so does this produce the same results as the R function dnorm running on # the CPU? f(1:10/2) - dnorm(1:10/2) # query whether device supports double-precision arithmetic, and if so, # use the capability 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")