# 算子的设计
算子是神经网络中用来处理加法 / 减法 / 激活函数等的抽象
# 算子基类
-
层的名字 / 类型:
-
线性 / Encode/Embedding/Softmax/Add 等
-
算子类型: dataType: fp32/int32 等这种
-
设备类型: CPU/GPU 即 Layer 即可以在 CPU 上实现,也可以在 GPU 上实现
-
算子有输入,且输入可能并不唯一,所以设计上通常会提供一个接口: set_input (index,Tensor) 这样,第一个参数表示输入参数的下标.
-
输出同理
-
算子的计算过程:通常以 base_forward 来命名,每个算子重写 base_forward 来进行算子的计算,同时将数据存放到 output 中
-
算子计算前的输入检测,因为传入的是 Tensor,所以需要检查输入的 Tensor 是否可以进行当前算子的计算、或者输入与层是否都在 CPU/GPU 上等
-
含参数的算子:通常加入一个 weights<Tensor 列表> 代表算子权重 (参数)
如 AddKernel 的实现,在 get_kenel 阶段根据层的类型选择对应的 kernel 类型,如 CPU/GPU:
1 | void add_kernel_cpu(const tensor::Tensor& input1, const tensor::Tensor& input2, |
# 以 RMSNorm 算子为例,它的 CUDA 实现
RSMNorm 算子公式:
# CPU 上 RMSNorm 的实现
1 | void rmsnorm_kernel_cpu(int32_t dim, const tensor::Tensor& input, |
# CUDA 上的算子实现
1 |
|
WrapReduce 实际上用的是 ShuffleWarpReduce,即:
1 1 1 1 1 1 1 1
2 2 2 2
4 4
8
这样规约,这样规约可以避免线程阻塞,因为可以确保每一轮都是同时进行的,所以可以直接把后面的加到前面的,然后不断地缩减规模,达到类似归并的效果,结果在线程 0 上
# 启动 CUDA 上的 rmsnorm 核函数
和直接调用函数即为相似
1 | void rmsnorm_kernel_cu(const tensor::Tensor& input, const tensor::Tensor& weight, |