我在统计如下代码耗时的时候,发现有这么个问题。
这段代码是对im和meanparameter两个指针对应数据做加法,在STM32F746上运行。通过DWT-CYCCNT来计算时间。其中两个做加法的指针指向两个随机生成的float数组,运算使用了FPU。对于每一种size,做一万次运算后取平均值,即为该size下的平均耗时
然而随着我增加size的大小,却发现循环耗时不是跟着size增加呈线性变化的。
如图所示,在800之前,拟合的曲线是个二次方函数,甚至R是1.
其中常数项29可以解释,图中的这个曲线是包括做加法的这个函数的压栈出栈和参数传递的时间。再加上branch的时间和CYCCNT置零后的时间,大概就是29左右。
其中一次方系数也可以解释,就是while 这个loop,每个loop的平均耗时。
二次方系数我就不知道是什么了。
进一步的,我把size加到一万之后,zise与耗时关系图长这样
发现一次方系数变大,二次方系数几乎没有了。
到目前为止大概是正常的,但是把一次方项系数单独拿出来说之后,有个奇怪的图像就出来了。
上图是size与一方次系数的关系图,比如在5000的那个点,就是对0~5000的几个点进行拟合得到的一次项的系数。
发现随着size变大,一次方系数由1时候13迅速的在800左右减小到5,然后稳定到7附近。简直是个完美的,滤波过程。pid?
最开始发现这个问题的时候,我以为是数据的问题,比如FPU数据对齐需要花费时间,对齐用的时间不同,计算速度也就不同,但是我用随机生成的数据测试依然有这种情况,说明不是数据的问题。
后来怀疑是fpu的问题,然后我使用随机生成的0~1024的数据来测试,结果是这样的
他的一次方系数是这样的
这就很奇怪了,这说明如果我要算一个加法循环,最有效率的循环次数是二百左右(用总耗时除以循环次数)。无论大了还是小了效率都会变低。尤其是如果循环只有十几次的话,效率是非常低的。
暂时没有测试乘法,因为我现在觉得是branch predictor的问题,但又觉得不像,因为分支预测的准确率应该至少95%才对,不应该出现波动这么大的情况(从十三到五,说明这个一开始的refill都浪费了七八个周期)。如果真的是分支预测的问题,其他核是不是也存在这么一个,最佳循环次数呢?
/
我没有测一万次的总时间,我在这个while(size--)前后布置了DWT,,用来测试wile(size--)的执行时间,外面那个大循环while(一万--)跟这个while(size--)中间还有好多别的程序比如产生随机数据,printf
while(一万--)
{
一堆其他程序
DWT->CYCCNT=0;
while(size--)
}
num=DWT->CYCCNT;
printf(num-1);
测一万的总时间再除以一万就不如测一万次除以一万来的精确了。不太明白外面的大while怎么影响小while的运行,毕竟每次小while之前我都把计数器清零