tl; dr: double b=a-(size_t)(a)
快于double b=a-trunc(a)
我正在为图像实现旋转功能,我注意到trunc
函数似乎非常慢。
为图像循环代码,对像素的实际影响进行了注释,以进行性能测试,因此我甚至无法访问像素。
double sina(sin(angle)), cosa(cos(angle));
int h = (int) (_in->h*cosa + _in->w*sina);
int w = (int) (_in->w*cosa + _in->h*sina);
int offsetx = (int)(_in->h*sina);
SDL_Surface* out = SDL_CreateARGBSurface(w, h); //wrapper over SDL_CreateRGBSurface
SDL_FillRect(out, NULL, 0x0);//transparent black
for (int y = 0; y < _in->h; y++)
for (int x = 0; x < _in->w; x++){
//calculate the new position
const double destY = y*cosa + x*sina;
const double destX = x*cosa - y*sina + offsetx;
所以这是使用trunc
size_t tDestX = (size_t) trunc(destX);
size_t tDestY = (size_t) trunc(destY);
double left = destX - trunc(destX);
double top = destY - trunc(destY);
这是更快的等价物
size_t tDestX = (size_t)(destX);
size_t tDestY = (size_t)(destY);
double left = destX - tDestX;
double top = destY - tDestY;
答案建议在转换回积分时不要使用trunc
,所以我也尝试过这种情况:
size_t tDestX = (size_t) (destX);
size_t tDestY = (size_t) (destY);
double left = destX - trunc(destX);
double top = destY - trunc(destY);
快速版似乎需要平均30毫秒才能完成整个图像(2048x1200),而使用trunc
的慢版本需要大约135毫秒才能完成相同的图像。只有两次调用trunc
的版本仍然比没有调用的版本慢得多(约100ms)。
据我理解C ++规则,两个表达式应该总是返回相同的东西。我在这里错过了什么吗? dextX
和destY
被声明为const
,因此只应对trunc
函数进行一次调用,即使这样,它也无法解释速度超过三倍的因素。
我正在使用Visual Studio 2013进行优化(/ O2)。是否有理由使用trunc
功能?即使使用整数获得小数部分似乎也更快。
答案 0 :(得分:4)
您使用它的方式,根本没有理由使用trunc
function。它将双变换为双精度,然后将其转换为积分并扔掉。事实上,替代方案更快,并不令人惊讶。
答案 1 :(得分:3)
在现代x86 CPU上,int&lt; - &gt;浮点转换非常快 - 通常为转换生成内联SSE代码,成本大约为几个指令周期。 1
对于var users = [new User({name: 'test'})];
<li ng-repeat="user in users"></li>
,但是需要函数调用,并且单独的函数调用开销几乎肯定大于内联浮点数的成本 - &gt; int转换。此外,trunc
函数本身可能相对昂贵 - 它必须完全符合IEEE-754标准,因此必须正确处理全范围的浮点值,例如NaN,INF等边缘情况。否则,超出范围的值等等。总的来说,我认为trunc
的成本大约为几十个指令周期,即一个数量级或大于内联浮点数的成本 - &GT; int转换。
<小时/> 注意浮动&lt; - &gt; int转换并不总是很便宜 - 其他CPU系列,甚至更旧的x86 CPU,可能没有ISA支持这种转换,在这种情况下通常会使用库函数,其成本类似于{{ 1}}。现代x86 CPU就是这方面的特例。