赞
踩
本人使用C++版本的TensorRT框架做模型部署的开发工作,在实际上线具体的项目过程中碰到过检测时间不理想的情况,所以本人专门为此写一篇博客记录曾经遇到过的坑以及对应的解决方案。
两台相同型号的机器、相同型号的显卡,在做分割项目时检测结果都一样,但是检测速度却不同。
将每个模块的耗时打印出来,来观察哪一个模块耗时不相同,本人分成了以下5个部分:
a.前处理
vector< cv::Mat >—>float *
b.数据送内存到显存
cudaMemcpyAsync(mBinding[bindIndex], input, mBindingSize[bindIndex], cudaMemcpyHostToDevice, stream);
c.前向传播(调用 executeV2 (bindings))
mContext->enqueueV2(&mBinding[0], stream, nullptr);
d.数据从显存到内存
cudaMemcpyAsync(output.data(), mBinding[bindIndex], mBindingSize[bindIndex], cudaMemcpyDeviceToHost, stream);
e.后处理
vector< float > —>vector< cv::Mat >
最终发现在数据从显存到内存传输的过程中,时间是不相同的。
(cudaMemcpyAsync in cudaMemcpyDeviceToHost mode)
经过本人一番搜索后,了解到有个设置会干扰这部分时间,就是分页内存。
长话短说就是设置无分页内存可以让速度达到最快,而设置虚拟内存会导致速度变慢。
对系统设置无分页内存。
具体操作:
a.搜索栏搜索 高级系统设置
b.点击性能中的设置
c.点击高级中的更改
d.点击 无分页文件 再点击右边的设置
e.最后点确定然后重启计算机即可。
部分机器上检测时间会非常不稳定,比如理论上应该是30ms一张图,但是隔几张之后就变成100ms以上,然后又变成30ms。但是同一套程序在部分的机器上又是稳定的,所以排除了代码问题。
而且除了TensorRT框架外,本人使用Libtorch框架做的检测项目也发生了类似的情况,所以或许问题点不在TensorRT本身。
仍然按照上述问题一的思路。
仍然是数据从显存到内存的时间不稳定所导致的。
(cudaMemcpyAsync in cudaMemcpyDeviceToHost mode is slow)
PS:到这里可以得出个大概规律,TensorRT的耗时有问题很有可能是数据从显存到内存这个地方导致的。
经过了本人地毯式的搜索,并没有找到与本人相同的问题以及解决方案。
本人只能根据手上有的机器以及显卡来猜测究竟是哪个因素导致检测时间有较大波动。
本人猜测了显卡型号、精度模式(FP16 or FP32)、CPU型号、CPU核心数等等因素,都被否决了。
最后本人发现一个很神奇的点,那就是检测时间稳定的机器上显卡驱动版本都是500以下的,而检测时间不稳定的机器上显卡驱动版本都是500以上的,于是乎本人试了下将显卡驱动为512的一台机器显卡驱动降级到472.84版本,没想到检测时间变稳定了!
当时第一反应就觉得是这个版本问题。但是本人下载的这个驱动是通过驱动精灵下载的,不是DCH版本,而是标准版本。本人又猜想莫非是DCH和标准的区别而导致的?
于是本人又下载了个DCH版本的472.84的显卡驱动,安装完后发现时间仍然是稳定的。
到这里基本可以断言,数据从显存传到内存这一环节与显卡驱动版本是有关系的!至少本人这里400~500的版本是没问题,而512版本的驱动会导致速度不稳定!
直接将512版本的显卡驱动降级,降到470左右的版本。
具体操作:(建议按照本人操作来,因为会有坑)
a.首先搜索栏搜索设备管理器
b.点击显示适配器,底下应该有个属于自己机器的显卡,右键点击它,然后点击卸载设备,再卸载驱动,接着重启电脑。
c.重启电脑之后先看下还有没有英伟达控制面板,有的话看看有没有降级到4XX的版本,如果有的话,就直接试试看应该可以稳定检测了。
如果连英伟达控制面板都没有的话,就下载驱动精灵,然后它会提示更新驱动,此时显示的是一个472.82的标准版驱动。点击它让它更新。(截图中箭头的地方一开始是升级驱动,点击它)
本人将这个版本的驱动放到了阿里云盘,也可以直接通过下面本人的阿里云盘链接直接下载
https://www.aliyundrive.com/s/CtTUuETiPfg
Tip:
如果这一步直接使用的是NVIDIA官网的DCH驱动的话,安装的时候会报错。
d.更新完驱动后再次打开程序,这个时候程序检测时间就变得稳定了。
当然由于本人在编译TensorRT环境的时候,显卡驱动是472.88版本,所以与显卡驱动512版本会有不兼容的情况。
下一步本人打算在显卡驱动为512版本的机器上重新编译,然后再试一下能否稳定运行,后续会更新实验结果。
2022.09.26更新:
本人在512版本的显卡驱动上重新编译和测试,时间仍然是不稳定的。而且
所以基本可以得出结论:
显卡驱动版本在500以上的会导致TensorRT推理时间不稳定,建议换成500以下的。
本人在NVIDIA官网上提交此问题,目前正在等待NVIDIA官网的回复。
The time of cudaMemcpyAsync() in cudaMemcpyDeviceToHost mode is unstable after upgrading the graphics card driver to version 512
2022.09.28更新:
本人在类似的一篇帖子中发现推理时间变慢跟GPU时钟频率有关系,所以本人试着将GPU频率给锁死,结果是速度变稳定了,而且甚至比原来快了3ms左右!
如果本人输入的是最高频率,那么就会很稳定,但是如果输入的不是最高频率,仍然会间隔10几张图之后有跳动。
将GPU时钟频率锁死的具体操作:
用管理员的方式打开cmd(不用管理员的方式后面可能会报错),然后输入nvidia-smi -q -d SUPPORTED_CLOCKS,看最大的时钟频率是多少,比如本人的结果如下图所示。
接着输入nvidia-smi -lgc 7501,成功后会有如下的提示。
问题来了,如果本人输入的不是7501,比如输入7001的话,仍然会间隔十几张图后不太稳定,如下图所示:
参考资料:
深度学习显卡驱动设置?
2022.10.06更新:
NVIDIA官方给出了回复,如下图所示。
翻译过来就是
1.不用分页内存,使用固定内存
2.设置时钟频率为最高频率
两个做法我都有做过,但是并没有给出正面的回答(为什么跟显卡驱动版本有关)。
2023.02.08更新:
关于检测时间波动还有可能最直接的一点原因就是内存快占满了,本人在最近的一个6个模型并行推理的项目部署中发现两台机器,显卡型号一样,但是一个是内存8G,一个是内存16G,8G的机器推理速度就经常有波动(最慢的达到200ms一张图),而16G的机器推理速度就比较稳定(最慢的也只有60ms一张)。
仔细一检查,发现8G内存的机器的内存占用率已经达到快90%了,所以由此可以看出内存占得太满的话,会影响推理速度。
2023.05.17更新:
最近因为老板让我尝试下在不让驱动版本降级的情况下能否稳定推理速度,于是我尝试了下直接在500多的版本下锁死最大时钟频率,发现这样一步就能直接变稳定了!
但是如果这个时候显卡驱动版本自动更新了(比如说从516升级到531),那么这个锁死时钟最大频率的命令行就又得再来一次。
但是本人发现又一件奇怪的事,如果我用批处理文件(新建一个txt,输入你想要输入的命令行内容,关闭,修改后缀为bat)的方式锁死最大时钟频率的话,哪怕驱动自动更新也仍然是稳定的!如果读者发现自动更新后变得不稳定可以尝试试下这招,也欢迎评论区留言交流。
2023.06.02更新:
最近发现在显卡驱动版本500以上的显卡上还是会有速度不稳定或者速度稳定但是明显耗时变长的情况。
于是又重新做实验解决问题,最终发现按照如下方案能够解决问题:
首先锁死最大时钟频率,然后设置NVIDIA控制面板的管理3D设置中的低延时模式为超高,设置电源管理模式为最高性能优先,保存应用,最后需要重启电脑。
经过这完整的三步之后,就能让TensorRT模型稳定地运行下去了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。