Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PPQ INT8 导出到 onnx 平台性能较低的可能原因 #330

Closed
Pzzzzz5142 opened this issue Dec 14, 2022 · 8 comments
Closed

PPQ INT8 导出到 onnx 平台性能较低的可能原因 #330

Pzzzzz5142 opened this issue Dec 14, 2022 · 8 comments

Comments

@Pzzzzz5142
Copy link

之前在另一个 issue #329 下面提到了,感觉还是另开一个新 issue 比较好。

目前ppq在int8上表现不好的原因有可能就是因为导出格式的问题所导致的。因为相比未量化的模型,ppq导出的模型不仅额外引入了量化与反量化的操作,还使用了fp32进行计算。这里onnx官方的int8模型并不是这样导出的,而是使用了 QLinearConv 等量化数据专用算子进行运算。这里以 mobilenet 为例,下载仓库在这里。如图所示的是未量化的模型和官方量化的模型:
image
image

下图是ppq在指定导出平台为 ONNXRUNTIME 量化得到的模型:
image

可以看到,官方实现由于使用了适用于量化后数据的 QLinearConv 等算子,并没有频繁的插入量化和反量化算子,同时还考虑到了图优化(比如他把 clip 给优化了,但这里还有可能能优化的点在于这种 QConv 接 QConv 可能也是可以融合的),但 ppq 不仅使用了非常多的量化和反量化算子,还使用了 fp32 进行实际运算。这可能是导致 ppq 导出的 onnx 模型低效的原因。

这只是一个猜想,不一定对(逃

@ZhangZhiPku
Copy link
Collaborator

ZhangZhiPku commented Dec 15, 2022

其实那个QLinearConv格式一样很烂,不仅性能烂,支持的人也少....

它更可能的原因是onnxruntime压根就没怎么写好int8...

@Pzzzzz5142
Copy link
Author

(啊这样吗(那麻烦问一下后续ppq有支持QLinearConv的计划吗?
如果没有,那请问我后续开发中是否直接想办法去除多余的dequant就好了?(

@vacing
Copy link

vacing commented Dec 15, 2022

它更可能的原因是onnxruntime压根就没怎么写好int8...

profiling 对比过性能,确实没有什么提升,int8 是用nhwc 实现的, 还要插入转换节点,怀疑是实现不好

@vacing
Copy link

vacing commented Dec 15, 2022

。这里onnx官方的int8模型并不是这样导出的,而是使用了 QLinearConv 等量化数据专用算子进行运算。

onnx 量化支持两种表示,qdq 或者量化算子,你这里应该是选的量化算子,感觉对实际推理应该没什么影响

@Pzzzzz5142
Copy link
Author

profiling 对比过性能,确实没有什么提升,int8 是用nhwc 实现的, 还要插入转换节点,怀疑是实现不好

麻烦问一下性能大概是什么水平的呢?和fp32与fp16相比的话

@Pzzzzz5142
Copy link
Author

onnx 量化支持两种表示,qdq 或者量化算子,你这里应该是选的量化算子,感觉对实际推理应该没什么影响

原来如此,那感觉还是得手动去做qdq模式的parse了(

@ZhangZhiPku
Copy link
Collaborator

(啊这样吗(那麻烦问一下后续ppq有支持QLinearConv的计划吗? 如果没有,那请问我后续开发中是否直接想办法去除多余的dequant就好了?(

引入 QlinearConv, QlinearGemm, QConcat 这几个算子会让事情变得更复杂,正如我们之前提到的:onnx 需要引入一组 Quant/Dequant 节点来传递算子的量化信息,而不能使用单个的 Quant 节点,这是因为在 onnx 的算子定义中,很多算子只可以接受 fp32, fp16 的数据作为输入,不可以接受 int32, int16, int8。QlinearConv 算子截然相反,它接受 int8 但不接受 fp32,这样的性质导致带有 QlinearConv 的 onnx 会显得拖泥带水——为了避免 QlinearConv 与 fp32 的数据直接接触,在网络中仍然会有一堆 Quant 节点来完成数据类型的转换,解析起来更加麻烦,而且导出的时候我们还得去判断 variable 的数据类型。

PPQ 在 0.6.3~0.6.5 中是有 QlinearConv 格式支持的,但是对于复杂的模型上述格式存在各种 bug,于是后来就移除了。这个格式会导致模型解析遇到更多困难,挺离谱的。

@Pzzzzz5142
Copy link
Author

👌,感谢回复!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants