最近在使用二维Gamma校正的过程中了解到了矢量化编程,顿时产生了兴趣。
在matlab的日常使用中,处理整个矩阵的时候通常会使用for循环嵌套,但往往这样会比较慢,而采用矩阵直接运算则会快很多,但也没有去细想原因。直到最近在需要实现在嵌入式设备上使用二维gamma校正,为了方便调试,选择了在matlab上先用接近c语言的写法去实现该功能,然后在其基础上移植到C语言版。根据要求,需要对一张原图像做卷积运算,原图尺寸1600*1200,而二维高斯卷积核尺寸达到1200*1200,且有三个同尺寸的不同尺度的二维高斯卷积核,需要做多次卷积运算。
若使用接近C语言的写法实现该功能,则使用for循环最多的时候会达到4层嵌套,这会带来巨大的时间损耗,相比于最开始调用系统函数fspecial和imfilter去实现二维gamma校正,时间损耗差异非常巨大。(测试电脑硬件为i5 9400f+N卡1650+金士顿骇客神条16G 2666 )使用系统函数时间也就十来秒,而自己使用for嵌套实现的函数根据计算需要跑几十个小时,这个时间让我感到绝望。
于是开始思考系统函数这么快的原因,在这过程中,了解到了矢量化编程。之所以系统函数这么快,主要就是因为使用了矢量化编程,说直白点,就是在对矩阵内元素进行操作的过程中采用矩阵运算,对于矩阵的每行每列,可认为在矩阵计算时均是相互独立的,采用并行计算,给每行每列的计算各自开一个线程,相比于for循环每次只计算矩阵中一个元素自然速度就快了很多。
另一方面,在老版本的matlab中,对于.m文件代码,Matlab是解释执行的,解释执行比编译执行慢。而在2015及以上的版本中,貌似引入了 JIT 并且对其引擎进行了升级,MATLAB 会对代码做优化,而不再只是一句句解释执行。因此for循环的速度得到很大提升, 经常有for循环快于向量化运算。
有趣的是,我使用的matlab版本刚好是2014版。。。。。。