Call OpenCL from Kotlin or embed OpenCL inside Kotlin

Submitted by Dickens A S on Fri, 11/29/2019 - 17:29

Embedded OpenCL inside Kotlin

GitHubhttps://github.com/dickensas/kotlin-gradle-templates/tree/master/embed-opencl

OpenCL code which runs from kotlin

#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
__constant char hw[] = "Hello World";
__kernel void hello(__global char * A) {
    size_t tid = get_global_id(0);
    A[tid] = hw[tid];
}

 

Kotlin code which runs OpenCL

package plot

import kotlinx.cinterop.*
import opencl.*
import platform.posix.intptr_t
import platform.posix.size_tVar

var code = 
"""
#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
__constant char hw[] = "Hello World";
__kernel void hello(__global char * A) {
    size_t tid = get_global_id(0);
    A[tid] = hw[tid];
}
"""

fun main() {
    
    println ("code which will call opencl");
    
    memScoped {
        var platform = alloc<cl_platform_idVar>()
        var device =  alloc<cl_device_idVar>()
        var props = allocArray<cl_context_propertiesVar>(3)
        props[0] = CL_CONTEXT_PLATFORM.toLong()
        props[1] = 0.toLong()
        props[2] = 0.toLong()
        
        clGetPlatformIDs( 1, platform.ptr, null )
        var err = clGetDeviceIDs( platform.value, CL_DEVICE_TYPE_GPU, 1, device.ptr, null )
        if (err != CL_SUCCESS) { throw Error("Unable to enumerate device IDs") }
        props[1] = platform.value.toLong()
        
        var errCtx = memScoped { alloc<cl_intVar>() }
        var ctx = clCreateContext( props, 1, device.ptr, null, null, errCtx.ptr )
        if (ctx == null || errCtx.value != 0) { throw Error("Unable to create context") }
        
        var queue = clCreateCommandQueue( ctx, device.value, 0, errCtx.ptr )
        if (queue == null || errCtx.value != 0) { throw Error("Unable to create queue") }
        
        var program = clCreateProgramWithSource( ctx, 1, arrayOf(code).toCStringArray(memScope), null, errCtx.ptr)
        if (program == null || errCtx.value != 0) { throw Error("Unable to create program") }
        
        err = clBuildProgram( program, 0, null, null, null, null)
        if (err != CL_SUCCESS) { throw Error("Unable to build program") }
        
        var kernel = clCreateKernel( program, "hello", errCtx.ptr)
        if (kernel == null || errCtx.value != 0) { throw Error("Unable to create kernel") }
        
        var N = alloc<size_tVar>()
        N.value = 12.toULong()
        var B = allocArray<ByteVar>((N.value.toInt()+1 * sizeOf<ByteVar>()).toInt() )
        
        var output = alloc<cl_memVar>()
        output.value = clCreateBuffer( ctx, CL_MEM_WRITE_ONLY.toULong(), (N.value.toInt()+1 * sizeOf<ByteVar>()).toULong(), null, errCtx.ptr)
        if (errCtx.value != 0) { throw Error("Unable to create buffer") }
        
        err = clSetKernelArg(kernel, 0, (sizeOf<cl_memVar>()).toULong(), output.ptr)
        if (err != CL_SUCCESS) { throw Error("Unable to set arguments") }
        
        clEnqueueNDRangeKernel( queue, kernel, 1, null, N.ptr, N.ptr, 0, null, null)
        
        clFinish(queue)
        
        clEnqueueReadBuffer( queue, output.value, CL_TRUE, 0, (N.value.toInt()+1 * sizeOf<ByteVar>()).toULong(), B, 0, null, null );
        clFinish(queue);
       
        println(B.toKString())
        
        clReleaseMemObject( output.value )
        clReleaseCommandQueue ( queue )
        clReleaseContext ( ctx )
    }
}

You need to install MSYS2 and opencl using below command

pacman -S mingw-w64-x86_64-opencl-headers mingw-w64-x86_64-opencl-icd-git

If segment fault occurs or buffer allocation fails, try to execute few more times

 

For Python use is code embed python in kolin

For Ruby use this code embed ruby in kotlin

For Lua use this code embed lua in kotlin

For R use this code embed R in kotlin

 

Add new comment