PoCL Runtime开发需要做的工作主要有以下几个方面:
- 实现UMD API;
- 实现KMD API;
- 制作交叉编译tool chain;
- 编写交叉编译脚本
下面咱们一个一个看。
1 UMD API
开源PoCL代码中有些例子是可以参考的,路径在pocl/lib/CL/devices,有:
- basic:以host CPU作为target device,仅有一个执行单元
- cuda: NV GPU为target device
- pthread:也是以host CPU作为target device,但每个线程作为一个执行单元,可模拟多核执行单元
- 其它:还有很多,不一一列举。
假如,我的target device架构为RISC-V,在pocl/lib/CL/devices路径下添加一个文件夹,参考例子实现即可。我认为在初期端到端流程打通阶段,参考以上三个就可以了,后期根据芯片自定义特性再迭代增加。
下面分几大部分展开讲。
1.1 Runtime 初始化
Runtime API:pocl_xx_init,第一次创建clGetDeviceIDs时调用.
此处及以下,xx代表设备识别名称,如pocl_basic_init
步骤:
1.设置设备初始化信息,包括:设备类型、厂商名称及ID、支持OpenCL版本及相应能力属性、printf_buffer size;
2.通过kmd API获取设备当前属性信息
a.xxGetDevice:获取设备信息;
b.xxDeviceGetName:获取设备名称;
c.xxDeviceGetAttribute:获取设备属性,如:
i.MAX_THREADS_PER_BLOCK
ii.MAX_BLOCK_DIM_X
iii.MAX_BLOCK_DIM_Y
iv.MAX_BLOCK_DIM_Z
d.xxDriverGetVersion:获取当前driver版本信息;
e.xxMemGetInfo:获取当前可用memory大小及memory总大小。
3.初始化device_data;
4.配置builtin kernels,包括OpenCL builtin kernel及GW自定义builtin kernel.
注意:umd高度依赖kmd API,由kmd提供对device的基本操作。
1.2 内存管理
Runtime API:
1.pocl_xx_alloc_mem_obj
2.pocl_xx_submit_read
3.pocl_xx_submit_write
4.pocl_xx_submit_copy
1.3 任务调度
Runtime API:pocl_xx_init_queue,clCreateCommandQueue时调用
步骤:
1.初始化任务队列
a.初始化互斥信号量: queue_data->lock
b.初始化条件信号量:pending_cond和running_cond
c.初始化submit线程
d.初始化finalize线程
队列数据结构定义:
typedef struct pocl_xx_queue_data_s
{
int use_threads;
pthread_t submit_thread;
pthrea