请教下大神,
目前看到mtl每次predict时,多个task是for顺序执行的,
看到代码里有说到“We could parallelize this in the future”
请问如何并行起来?有什么思路吗?感谢!
请教下大神,
感谢大佬回复!hanlp model是不是也不能转onnx?我自己尝试了下,各种坑很麻烦。方案1确实开销很大,比for慢多了。对于大佬说的方案2,有什么tutorial可以参考的吗?我想继续尝试下,但不知道应该搜哪方面的资料
理论上是可以转的,有如下难点:
torch.onnx
无法trace的。总之,如果只关注一个固定的task set自然可以硬编码并且转ONNX;否则的话,一个通用的框架则很难。虽然MTL整体难以trace,不过一旦任务和batch确定,Transformer和每个decoder都是可以导出ONNX的。
我们线上服务器对Trie
实现C++双数组trie树的时候,用的是swig,现在似乎更推荐Cython了。
每个task的prediction包括三个步骤:feed_batch、decode_output和prediction_to_result。大致思路是,每个task的feed_batch
保持原样放在for loop里,因为主要是CUDA运算,decode_output
看情况,有的是CUDA上的算法比如eisner,有的是CPU上的。然后在整个for loop结束后用Cython在C++里面开一个线程池并行执行每个task的prediction_to_result
。当然,这些prediction_to_result
都要用C++写。对于大部分任务都比较简单,基本就是把id转为string。
虽然没有用hanlp做部署,但我为了让自有的框架的MTL在onnx上部署是这么做的: 预测模型从训练模型拷贝weights, 切分成主干和branches, task调度放在cpu里
onnx处理变长序列应该只能bucketing, 对于pytorch来说好像有点棘手
的确是个好办法。
HanLP是支持将相似长度的句子归入同一个batch的,对 O(n^3) 的self-attention来讲是很省时间空间的。如果ONNX只支持512 padding的话,会不会比Python端更慢呢
应该会吧,没具体测过onnx对比pytorch的overhead,但padding是影响更大的
在我的代码上,基于tf的bucketing, 序列长度和耗时呈线性关系
综合上面的讨论,Python目前在部署上暂时还行。更何况根据《Deep Learning with PyTorch》作者的经验,即使你把推理从Python迁移到C++,性能也顶多提高10%。
面向未来,我觉得Python不是最佳选择。毕竟NLP不像CV那样基本全部依赖GPU运算,还是有相当一部分运算(预处理)是在CPU上的,而Python整个的内存管理和并行都太弱了。就像huggingface的tokenizer一样,可能把这部分逻辑用Rust重写一遍才是又快又经济的。
确实大部分耗时都是预处理和后处理,viterbi解码这些东西。
百度开源的分词工具LAC,使用的是GRU,在cpu端的推理优化做的很到位(好像用的是mkldnn),crf解码用的avx指令,分词速度还不错
HanLP的Viterbi是矩阵并行的,在CPU上PyTorch应该也有相应的MKL加速或本地指令集。