library(OpenCL)
## Only proceed if this machine has at least one OpenCL platform
if (length(oclPlatforms())) {
ctx = oclContext(precision="single")
code = c("
__kernel void dnorm(
__global numeric* output,
const unsigned int count,
__global numeric* input,
const numeric mu, const numeric sigma)
{
size_t i = get_global_id(0);
if(i < count)
output[i] = exp((numeric) (-0.5 * ((input[i] - mu) / sigma) * ((input[i] - mu) / sigma)))
/ (sigma * sqrt((numeric) (2 * 3.14159265358979323846264338327950288 )) );
}")
k.dnorm <- oclSimpleKernel(ctx, "dnorm", code)
f <- function(x, mu=0, sigma=1)
as.numeric(oclRun(k.dnorm, length(x), as.clBuffer(x, ctx, "numeric"), mu, sigma))
## expect differences since the above uses single-precision but
## it should be close enough
f(1:10/2) - dnorm(1:10/2)
## does the device support double-precision?
if (any("cl_khr_fp64" == oclInfo(attributes(ctx)$device)$exts)) {
k.dnorm <- oclSimpleKernel(ctx, "dnorm", code, "double")
f <- function(x, mu=0, sigma=1)
as.numeric(oclRun(k.dnorm, length(x), as.clBuffer(x, ctx, "double"), 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
}
Run the code above in your browser using DataLab