-
Notifications
You must be signed in to change notification settings - Fork 3
What is Kernel Mapper
The Kernel Mapper generates a python source code which calls Open CL kernel code. To generate a python code, Users should create a kernel definition file, a JSON file. With the python code, users can just create the object and call the function it exposed which are the kernel functions. It's pretty simple and easy to use.
The kernel definition file contains two parts:
As we known, it is possible to use struct in Open CL. This part defines the structs which are used at kernel functions, see next part. At generating phase, Kernel Mapper generates the struct header for your, like:
#ifndef __PRICE_DATA_H__
#define __PRICE_DATA_H__
typedef struct {
long dataIndex;
float open;
float high;
float low;
float close;
} PriceData;
#endifAll structs definition will be at a single header file, kernel_structs.h. You can just include this header file to have all structs.
At python source code, you may see the code like this:
self.PriceData = numpy.dtype([('dataIndex', numpy.int), \
('open', numpy.float32), \
('high', numpy.float32), \
('low', numpy.float32), \
('close', numpy.float32)])All structs will be defined as member variables in a single class.
As we mentioned before, this part is optional. If you only use primitive type, like byte, short, int, float, long, double, you don't need to write this part.
TODO
{
"name": "PriceData",
"fields": [
{ "name": "dataIndex", "type": "long" },
{ "name": "open", "type": "float" },
{ "name": "high", "type": "float" },
{ "name": "low", "type": "float" },
{ "name": "close", "type": "float" }
]
}This JSON object defines the PriceData we just mentioned in previous section. It uses primitive types as its fields.
This parts defines the functions we want to implement in Open CL. We can use the primitive types or struct types which are defined at previous part as the function arguments. After the generation, Kernel Mapper generates the function declaration for you, like:
#include "kernel_structs.h"
__kernel void test_donothing(const int range,
const int realSize,
__global PriceData* inBuffer,
__global PriceData* outBuffer) {
}At python source code, you may see the code like:
def test_donothing(self, range, realSize, inBuffer, outBuffer):
...
def prepareOutBuffer(self, size):
...The prepareOutBuffer function creates a numpy array with PriceData as its type and size as its length. Before calling test_donothing, user should call prepareOutBuffer to obtain a buffer for test_donothing.
TODO
{
"name": "test_donothing",
"arguments": [
{ "name": "range", "type": "int", "memoryType": "constant" },
{ "name": "realSize", "type": "int", "memoryType": "constant" },
{ "name": "inBuffer", "type": { "arrayType": "PriceData" }, "memoryType": "global" },
{ "name": "outBuffer", "type": { "arrayType": "PriceData" }, "memoryType": "global" }
]
}This JSON object defines the test_donothing we just mentioned in previous section. It uses two constant variables and two PriceData arrays as its arguments.
{
"name": "AwesomeJob",
"types": [{
"name": "PriceData",
"fields": [
{ "name": "dataIndex", "type": "long" },
{ "name": "open", "type": "float" },
{ "name": "high", "type": "float" },
{ "name": "low", "type": "float" },
{ "name": "close", "type": "float" }
]
}],
"functions": [{
"name": "test_donothing",
"arguments": [
{ "name": "range", "type": "int", "memoryType": "constant" },
{ "name": "realSize", "type": "int", "memoryType": "constant" },
{ "name": "inBuffer", "type": { "arrayType": "PriceData" }, "memoryType": "global" },
{ "name": "outBuffer", "type": { "arrayType": "PriceData" }, "memoryType": "global" }
]
}, {
"name": "test_donothing2",
"arguments": [
{ "name": "inBuffer", "type": { "arrayType": "PriceData" }, "memoryType": "global" },
{ "name": "outBuffer", "type": { "arrayType": "PriceData" }, "memoryType": "global" }
]
}]The generated files are: | -- awesome_job_structs.h -- awesome_job.c -- awesome_job.py
In the file awesome_job_structs.h, Kernel Mapper generates the content like:
#ifndef __PRICE_DATA_H__
#define __PRICE_DATA_H__
typedef struct {
long dataIndex;
float open;
float high;
float low;
float close;
} PriceData;
#endifIn the file awesome_job.c, Kernel Mapper generates a skeleton of kernel functions for you and you should implement the kernel function inside of the function, like:
#include "awesome_job_structs.h"
__kernel void test_donothing(const int range,
const int realSize,
__global PriceData* inBuffer,
__global PriceData* outBuffer) {
// Please implement your kernel code here.
}
__kernel void test_donothing2(__global PriceData* inBuffer,
__global PriceData* outBuffer) {
// Please implement your kernel code here.
}The awesome_job.py is the generated python source code. You don't need to write anything but use it. Just create object and call the function. The content looks like:
class AwesomeJob:
... #other members
self.PriceData = numpy.dtype([('dataIndex', numpy.int), \
('open', numpy.float32), \
('high', numpy.float32), \
('low', numpy.float32), \
('close', numpy.float32)])
def test_donothing(self, range, realSize, inBuffer, outBuffer):
...
def test_donothing2(self, inBuffer, outBuffer):
...
def prepareOutBuffer(self, size):
...
... #other functions