那一年,让我整个人升华的C++ BERT项目
The following article is from 李rumor Author rumor
来源 / 李rumor(ID:leerumorr)
内容经授权发布
大家好,我是rumor。
自己不是CS科班出身,压根没写过完整的C++项目,虽然有些Java基础,但到底几斤几两我还是蛮清楚的。
打比方的话,就是让第一次玩塞尔达、刚开完四个神庙、出了新手村的我直接去打盖农,悲壮之感难以言表。
1
整个人都不好了
但我作为新时代的自强女性,还是开启了冲向海拉尔中心的旅程。
第一步,就是搜集可以参考的开源项目。
Fortunately,我找到了知乎开源的cuBERT项目,作者写得特别清楚,并且同时提供了GPU和CPU版本,但老板看了速度之后仍不太满意,最终我靠着极强的搜索技术又找到了英伟达刚开源的fastertransformer,用Cuda C++直接实现了transformer底层运算,速度秒杀其他方案。
在经历了各种make、install的折磨之后,我终于摸清了如何在服务器配置相关lib并运行c++代码,也顺利跑通了官方demo,性能完全符合预期。但不能高兴得太早,因为这个库只有transformer层的实现,前面的tokenization、embedding、pooling都没有写。。所以,这意味着我要读懂源码,然后自己把剩下的补全。
第二步,我开始读源码改项目。
这里有碰到了第一个难点,就是跑官方给的模型没问题,但运行我们自己的模型后就出现了 nan 这个恐怖的结果。于是我开始使用 print 大法,但惊讶地发现 cuda 底层全是并行的,一打日志都是乱的。。。于是我学会了 synchronize,在每个 operation 之后同步再打印结果,最终花了两天时间定位了问题:原来是Softmax没加溢出保护。立刻给作者提issue,不过在等待作者回复的过程中我居然自己给改好了,还默默学会了 Parallel Reduction 算法。
期间我还会卡在各种各样的事情上,经常会卡上一两天,陷入自我放弃的漩涡。
最终还是搞懂了源码,搞懂了cuda运算,并加上输入输出层搞出了完整的C++ BERT。
但仅仅有个程序还是不够,服务接口在哪里呢?
第三步,整一个服务。
于是我又搜啊搜,找到了一个宝藏:TensorRT Inference Server。当时的版本提供以下超赞的功能:
支持单GPU上的多模型&单模型多实例 支持多种backends框架(TensorRT、Tensorflow) 动态Batch增加吞吐 提供负载均衡及状态监测
所以又花了几天把C++ BERT适配TensorRT框架,成功变成了服务。
变成服务之后又有问题,就是每次换机器都要重新配置环境并部署,于是我又学会了docker,减轻运维负担。
2
通关了!
整个改造差不多耗时小两个月,也是我工作至今记忆最深的一段时刻。
我永远忘不了,那种看着看着代码就想站起来掀桌子的感觉。可以一起体会下:
template
__inline__ __device__
T blockReduceMax(T val)
{
static __shared__ T shared[32];
int lane = threadIdx.x & 0x1f; // in-warp idx
int wid = threadIdx.x >> 5; // warp idx
val = warpReduceMax(val); // get maxx in each warp
if(lane == 0) // record in-warp maxx by warp Idx
shared[wid] = val;
__syncthreads();
val = (threadIdx.x < (blockDim.x >> 5 )) ? shared[lane] : -1e20f;
val = warpReduceMax(val);
return val;
}
当然也忘不了身边同事牺牲自己时间给我的帮助,还有lead和我一起翻了半天C++ Premier才解决问题的欣喜。
故事的后来很圆满,压测效果满意,成功服务了团队的BERT上线。包括后来我在20年初和其他两个大厂团队的人交流,都没有听到过更快的速度,甚至有同学直接质疑了我,因为他们的时延是我们的两倍。。。
3
去挑战一座山吧
现在回想起来,这段经历真的太宝贵了。虽然不想再经历一次,但自那以后我再也没怕过任何代码。
做算法也有了底气,我可是搞过CUDA C++的女人,别叫我调包侠。
如果想快速提升,那就去挑战一座山吧,找一个高质量的项目,读懂并进行修改,在一次次自我放弃中成长。
就像走过高考、走过考研、走过校招那样,过去那道坎就没什么了。
「调包的日子,单纯快乐」
看马云如何回应淘宝假货问题!
↓↓↓
推荐阅读: