具有浮动指数的二的快速幂[C]
本质上,我试图使用下面代码中计算的值,但是当我在所有具有自己速率的对象中存储这些值时,添加的字节刚好足以导致缓存丢失。而使用查找表显然无助于解决问题 因此,我正在寻找一种比标准幂函数更快地获得这些值的方法,由于可能的输入非常有限,有什么技巧可以使用吗具有浮动指数的二的快速幂[C],c,math,C,Math,本质上,我试图使用下面代码中计算的值,但是当我在所有具有自己速率的对象中存储这些值时,添加的字节刚好足以导致缓存丢失。而使用查找表显然无助于解决问题 因此,我正在寻找一种比标准幂函数更快地获得这些值的方法,由于可能的输入非常有限,有什么技巧可以使用吗 static inline double __attribute(( pure )) get_decay_rate(uint8_t rate) { if(rate >= 128) { return 65
static inline
double __attribute(( pure )) get_decay_rate(uint8_t rate)
{
if(rate >= 128)
{
return 65535.0/65536.0;
}
double k = pow(2, rate/8.0);
return (k - 1.0) / k;
}
/* pseudocode:
double k = (int) pow(2, k/8.0);
k = (k - 1) / k;
return log(65535/65536)/log(k);
*/
static inline
uint16_t __attribute(( pure )) get_decay_modulus(uint8_t rate)
{
if(rate <= 128)
{
return 1;
}
//turns out to be the same as the above pseudocode, for some reason.
return pow(2, (rate - 128) / 8.0);
}
静态内联
双属性((纯))获取衰减率(uint8 t率)
{
如果(速率>=128)
{
返回65535.0/65536.0;
}
双k=功率(2,速率/8.0);
回报率(k-1.0)/k;
}
/*伪代码:
双k=(int)功率(2,k/8.0);
k=(k-1)/k;
返回日志(65535/65536)/log(k);
*/
内联函数
uint16属性((纯))获取衰减模量(uint8速率)
{
如果(比率采用这条线:
double k = pow(2, rate/8.0);
基本上你在这里做的是把2提高到一个固定点数的幂
你可以利用pow(a,b+c)=pow(a,b)*pow(a,c)和一个非整数=整数部分+小数部分这一事实。因此,你用你的固定点数的整数部分计算pow,并将其乘以小数部分的pow
将8个分数指数存储在查找表中:
double fractionalPowersOf2[8];
for(int i = 0; i < 8; i++)
fractionalPowersOf2[i] = pow(2.0, i / 8.0);
您还尝试在每个函数中放置一个静态256长数组?还是一个静态128长数组?您的意思是rate/8.0
inint k=pow(2,k/8.0)
?类似地,在get_decation_modules
中,您引用了k
,但没有声明it@Hurkyl由于问题是缓存未命中,这意味着缓存中可以容纳的代码更少,因此它会移动问题,而不是解决问题。@oldrinb是的,我的意思是。(速率-128)/8这是整数除法吗?谢谢你,先生,这太完美了!@samgak Givendouble k=pow(2,rate>>3)*表[rate&7]
启用优化后,编译器将为您在指数上执行奇妙的位魔术。@user3386109:我担心语义是否真的允许奇妙的位魔术,并且怀疑它不会在整数计算中执行魔术。在任何情况下,ldexp
可能是这里使用的更好的函数,如果您愿意的话坚持调用浮点函数。(需要分析!)
double k = (double)(1 << (rate >> 3)) * fractionalPowersOf2[rate & 7];
double k = pow(2,rate>>3) * table[rate&7];