优化定点 sqrt
Optimizing Fixed-Point Sqrt
我做了我认为是一个很好的fixed-point square root algorithm
:
template<int64_t M, int64_t P>
typename enable_if<M + P == 32, FixedPoint<M, P>>::type sqrt(FixedPoint<M, P> f)
{
if (f.num == 0)
return 0;
//Reduce it to the 1/2 to 2 range (based around FixedPoint<2, 30> to avoid left/right shift branching)
int64_t num{ f.num }, faux_half{ 1 << 29 };
ptrdiff_t mag{ 0 };
while (num < (faux_half)) {
num <<= 2;
++mag;
}
int64_t res = (M % 2 == 0 ? SQRT_32_EVEN_LOOKUP : SQRT_32_ODD_LOOKUP)[(num >> (30 - 4)) - (1LL << 3)];
res >>= M / 2 + mag - 1; //Finish making an excellent guess
for (int i = 0; i < 2; ++i)
// | /
// | /
// _| V L
res = (res + (int64_t(f.num) << P) / res) >> 1; //Use Newton's method to improve greatly on guess
// 7 A r
// / |
// / |
// The Infamous Time Eater
return FixedPoint<M, P>(res, true);
}
但是,在分析(在发布模式下)之后,我发现这里的划分占用了该算法花费的 83% 的时间。我可以通过用乘法代替除法来加快 6 倍的速度,但这是错误的。不幸的是,我发现整数除法比乘法慢得多。有什么方法可以优化这一点吗?
如果此表是必需的。
const array<int32_t, 24> SQRT_32_EVEN_LOOKUP = {
0x2d413ccd, //magic numbers calculated by taking 0.5 + 0.5 * i / 8 from i = 0 to 23, multiplying by 2^30, and converting to hex
0x30000000,
0x3298b076,
0x3510e528,
0x376cf5d1,
0x39b05689,
0x3bddd423,
0x3df7bd63,
0x40000000,
0x41f83d9b,
0x43e1db33,
0x45be0cd2,
0x478dde6e,
0x49523ae4,
0x4b0bf165,
0x4cbbb9d6,
0x4e623850,
0x50000000,
0x5195957c,
0x532370b9,
0x54a9fea7,
0x5629a293,
0x57a2b749,
0x59159016
};
SQRT_32_ODD_LOOKUP
只是SQRT_32_EVEN_LOOKUP
除以sqrt(2)
。
重新发明轮子,真的,而且不是以一种好的方式。正确的解决方案是使用 NR 计算1/sqrt(x)
,然后乘以一次得到x/sqrt(x)
- 只需预先检查x==0
即可。
这要好得多的原因是 y=1/sqrt(x)
的NR步骤只是y = (3-x*y*y)*y/2
。这都是简单的乘法。
相关文章:
- 空基优化子对象的地址
- 关闭||运算符优化
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 返回值优化:显式移动还是隐式
- 人脸跟踪arduino代码的优化
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 纯函数,为什么没有优化
- 为什么大多数 pair 实现默认不使用压缩(空基优化)?
- 如何以优化的方式同时迭代两个间距不相等的数组
- 小字符串优化(调试与发布模式)
- 浮点定向舍入和优化
- Visual Studio 调试优化如何工作?
- 如果我重新定义 sqrt 函数,为什么使用 std::sqrt 失败?
- 为什么开关的优化方式与 c/c++ 中的链接不同?
- 线性优化目标函数中的绝对值
- GCC 会优化内联访问器吗?
- 为什么 GCC 不能优化出 'std::sqrt'?
- 优化定点 sqrt
- 是否有任何C++编译器能够优化 lround(pow(sqrt(i), 2)) 现在或不久的将来用 i 替换它