Open yinfan98 opened 1 week ago
你的PR提交成功,感谢你对开源项目的贡献! 请关注后续CI自动化测试结果,详情请参考Paddle-CI手册。 Your PR has been submitted. Thanks for your contribution! Please wait for the result of CI firstly. See Paddle CI Manual for details.
Sorry to inform you that 19619b4's CIs have passed for more than 7 days. To prevent PR conflicts, you need to re-run all CIs manually.
PR Category
Others
PR Types
New features
Description
给paddle添加int4量化的kernel和int4量化进行permute的kernel。
TL;DR
支持了一个GPU kernel,它能做int4 weight only量化的工作。并且能支持weight_only_linear (同时也能和反量化接口对齐,如果你想单纯做量化反量化看看。你可以这么执行代码)
当然,weight only linear也是支持的
int4 weight only quant总结
参考CPU的实现,SM70以上kernel的实现分几个步骤:
但是我们其实不需要这么复杂的实现,我们可以直接就按列进行pack。也能达到一样的效果。并且只需要两个kernel(加上量化需要三个kernel)。方法如下:
int4量化kernel
对于int4量化来说,我们分别实现了按行pack和按列pack。(为了让SM70版本的显卡也能正常工作QAQ) 对按列pack来说,它需要让两个int4pack成一个int8的数进行实现。在代码里,我们让上下两行组成一个int8的数,也就是按列进行的pack。
int4 permute kernel
对于int4量化,我们需要对输入数据进行重排来适配cutlass的快速反量化kernel。 在int4反量化端,我们观察反量化算子实现可以发现。最后所需的输出是:
参考cutlass的快速反量化实现。 int4快速反量化4个int8一组,能把int8的数据转换为fp16的。但它会改变数据的排布:
则我们可以推得在快速反量化之前,我们需要的数据是
上面一组数看上去没有任何的规律,但是我们可以给它做一点小小的调整,调整成下面的形式,只需要一些简单的位运算即可
我们知道,两个int4 pack成了一个int8,我们也可以把上面的数调整成int8的index
那么从
的坐标为
得到这个新的permute_kk(代码里的变量,描述列之间的permute),可以通过int8的permute_kk做一点小小的改变 从int8 permute转换为int4 permute int8
可以把它变成
% 8 * 2
简单的位运算kernel(最后执行)
从
到
我们可以每四个数一组,然后02 13 之间做低四位和高四位的交换即可。
int4 row interleave
对于int8的case,代码在相邻的两行中,每64个元素进行交织。但是对于int4的情况。代码就会在相邻的四行中,每32个元素进行交织。所以在permute的处理时,写成了
这样也符合预期。(写着写着天都亮了zzz)