在小米mix 2s + 高通骁龙 845 + Adreno 630 上测试了opencl版本的cv::dft()。
先看表格里面的描述:
名称
函数名
最大时间(ms)
平均时间(ms)
说明
cpu版本dft
cv::dft()
-
0.029448
未统计其他,仅cv::dft()函数的调用时间
opencl版本
cv::dft(UMat)
802.557000
0.202941
不计算mat与umat的拷贝,不计算umat的填充对齐
opencl中使用opencl计算的主函数
cv::ocl_dft()
802.553000
0.210583
cv::dft()包装了cv::ocl_dft(),这一层无太多性能损耗
ocl_dft第一步调用的子函数
ocl_dft_rows()
802.518000
0.1031
-
ocl_dft第二步调用的子函数
ocl_dft_cols()
338.004000
0.078061
-
对象池
OCL_FftPlanCache::getInstance().getFftPlan()
0.190000
0.000028
对象池很快,几乎不占用时间,可以忽略
opencl的核函数编译、绑定参数、计算
OCL_FftPlan::enqueueTransform()
464.393000
0.075685
-
核函数编译
enqueueTransform()
464.237000
0.019422
第一次编译很慢,以后会快很多。但是也不用重复编译才对
参数绑定
enqueueTransform()
0.122000
0.016015
绑定参数也很快
核函数执行
enqueueTransform()
1.167000
0.028805
-
有这样一些结论:
在调用cv::dft()的opencl版本以前,开一个线程空调用一次cv::ocl_dft(),这样核函数的编译时间就不会占用总调用时间了。
ocl::Kernel这里可以建立对象池,而不是每次调用都使用临时对象,这样的话,每次调用可以节约0.019422ms,性能可提升9.6%;
ocl::Kernel k(kernel_name.c_str(), ocl::core::fft_oclsrc, options);
如果采用GPU内存池,每次计算的输入和输出地址都不变,那么参数绑定环节的0.016015ms可以省略,性能可能提升7.9%
在我的cv::dft()的使用场景中,每次连续计算44个矩阵的数据。假设能够找到方法,把44次计算陆续加入队列,让GPU连续计算。假设GPU并发度支持44次计算同时进行,那么GPU版本的理论延迟是 0.202941/44 = 0.004612, 比CPU版本提升 6.39倍!
手机扫一扫
移动阅读更方便
你可能感兴趣的文章