PoCL Runtime开发笔记

PoCL Runtime开发需要做的工作主要有以下几个方面:

  1. 实现UMD API;
  2. 实现KMD API;
  3. 制作交叉编译tool chain;
  4. 编写交叉编译脚本
    下面咱们一个一个看。

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;
  pthread_t finalize_thread;
  pthread_mutex_t lock;
  pthread_cond_t pending_cond;
  pthread_cond_t running_cond;
  _cl_command_node *volatile pending_queue;
  _cl_command_node *volatile running_queue;
  cl_command_queue queue;
} pocl_xx_queue_data_t;

任务调度模型:
在这里插入图片描述

1.4 kernel编译

1.4.1 built-in function

built-in function是device特有的内置函数,通常用来获取device硬件信息和状态查询。
比如读取状态寄存器CSR里core id/cluster id.
路径可与opencl built-in function放在一起,如:pocl/lib/kernel/get_cluster_id.c

typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;

#define M_HARTID_REG   0x0F14  // 定义寄存器地址

uint8_t get_cluster_id()
{
    uint64_t mstatus;
    // Read the value of CSR defined by the macro M_HARTID_REG
    __asm__ volatile("csrr %0, %1" : "=r" (mstatus) : "i" (M_HARTID_REG));

    // Extract bits [23:16] from the CSR value
    return (mstatus >> 16) & 0xFF;
}

built-in function完成后,需要修改CMakeList构建文件,将built-in function编入库.

// CMakeList路径
pocl/lib/kernel/host/CMakeLists.txt

使用llvm-nm -g xx.bc命令查看确认,bitcode file中已包含get_core_id和get_cluster_id符号。

因为这些built-in function将来运行在riscv架构的device上,因此,需要使用目标结构的编译工具链进行编译。目标结构的编译工具链制作是另外一个话题,咱们单开一讲。

set(CLANG_FLAGS ${HOST_CLANG_FLAGS} ${CLANG_CPUFLAGS}
                  "--sysroot=/project/gw_toolchain/changyao.fu/usr/riscv-gnu-toolchain-musl/sysroot" 
                  "-ffreestanding" "-march=rv64imafv" "-mabi=lp64f" "-emit-llvm" "-ffp-contract=off")

1.4.2 kernel编译

将自定义算子写成kernel函数,同样需要将kernel编译成riscv架构的binary.
分析basic编译流程,如下:
2 Build program
Compiles an .cl file into LLVM IR.
2.1 From source
2.2 From binary

3 Compile and link
3.1 Compile parallel.bc
pocl_llvm_generate_workgroup_function_nowrite()
Links the input kernel LLVM bitcode and the OpenCL kernel runtime library into one LLVM module.
Output is a LLVM bitcode file that contains a work-group function and its associated launchers.

  1. copy only the kernel+callgraph from program.bc to parallel.bc.
  2. run pocl passes

3.2 Compile kernel.so.o
pocl_llvm_codegen()
Run LLVM codegen on input file (parallel-optimized).
Compile into native object file (.so.o).

3.3 Final linking step
Linking kernel.so.o -> kernel.so

以vecadd为例,完成以上步骤后,编译出vecadd.so,为workgroup function.
在这里插入图片描述
在这里插入图片描述
Generate executable binary
在这里插入图片描述
main.c怎么写呢?

for (unsigned long int z = 0; z < pc->num_groups[2]; ++z)
    for (unsigned long int y = 0; y < pc->num_groups[1]; ++y)
      for (unsigned long int x = 0; x < pc->num_groups[0]; ++x) {
        {
          _pocl_kernel_vecadd_workgroup ((unsigned char *)arguments, (unsigned char *)pc, x, y, z);
        }
      }
__asm__ volatile("wfi");
  • 26
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值