数学函数的表现?

cem*_*ate 4 c math performance cocoa

我正在使用图形加速度计数据,我正在尝试纠正重力.为此,我得到球面坐标中的加速度矢量,将半径减小1g,然后转换回笛卡尔坐标.每0.03秒在一个计时器上调用此方法:

//poll accleration
ThreeAxisAcceleration current = self.accelerationData;

//math to correct for gravity:
float radius = sqrt(pow(current.x, 2) + pow(current.y, 2) + pow(current.z, 2));
float theta = atan2(current.y, current.x);
float phi = acos(current.z/radius);

//NSLog(@"SPHERICAL--- RADIUS: %.2f -- THETA: %.2f -- PHI: %.2f", radius, theta, phi);

radius = radius - 1.0;

float newX = radius * cos(theta) * sin(phi);
float newY = radius * sin(theta) * sin(phi);
float newZ = radius * cos(phi);

current = (ThreeAxisAcceleration){newX, newY, newZ};

//end math
NSValue *arrayVal = [NSValue value:&current withObjCType:@encode(ThreeAxisAcceleration)];

if ([_dataHistoryBuffer count] > self.bounds.size.width) {
    [_dataHistoryBuffer removeObjectAtIndex:0];
}

[_dataHistoryBuffer addObject:arrayVal];

[self setNeedsDisplay];
Run Code Online (Sandbox Code Playgroud)

不知何故,重力校正的加入逐渐使我的代码变得非常缓慢.我发现很难相信这个数学量会减慢程序的速度,但如果没有它,它仍然可以贯穿我的整个显示方法,这种方法非常冗长.我有什么选择可以考虑避免这种情况吗?我错过了什么,或者数学是那么缓慢?我可以在// math和// end math标签之间进行注释,就可以了.

谢谢你的帮助.

PS可能很重要,它可能对谁感兴趣,我正在用可可编程,这个方法属于CALayer的子类,使用-drawInContext:实现.

nal*_*all 8

你在iPhone上吗?尝试使用这些函数的float变体:powf,sqrtf等

有肯德尔黑尔姆施泰特Gelner的回答点#4到更多信息这太问题.

  • 实际上,iPhone*确实具有硬件双精度.但是,在3gs上,单精度算法要快得多,因为它是在NEON单元而不是VFP上执行的.此外,数学库中的单精度入口点通常相当好,并且比相应的双精度函数更快. (3认同)

Jen*_*ton 6

缩短矢量的常规方法是:

float originalMagnitude = sqrtf(current.x * current.x, current.y * current.y, current.z* current.z);
float desiredMagnitude = originalMagnitude - 1.0f;
float scaleFactor = (originalMagnitude != 0) ? desiredMagnitude / originalMagnitude : 0.0f; // avoid divide-by-zero

current.x *= scaleFactor;
current.y *= scaleFactor;
current.z *= scaleFactor;
Run Code Online (Sandbox Code Playgroud)

也就是说,不,每秒33次调用一些触发功能不应该让你失望太多.另一方面,-[NSMutableArray removeObjectAtIndex:]对于大阵列来说可能会很慢.甲环缓冲器(使用NSMutableArray或结构的C数组)会更有效.


Jam*_*nes 6

除了理论上不可能简单地分解地球的引力这一事实外,我要采取的第一步是对你正在进行的每项操作(乘法,除法,罪,atan2等)进行基准测试,然后设计一种方法计算时间要长得多的操作(或避免计算有问题的操作).确保在基准测试中使用与成品中相同的数据类型.

这是时间/准确性权衡的典型例子.通常有多种算法用于执行相同的计算,您也可以使用LUT /插值.

当我制作自己的Wii风格的遥控器时,我遇到了同样的问题.如果您确定了昂贵的操作并且无法围绕它进行工程设计,那么请启动另一个问题.:)

  • 勇敢地观察提问者想要做什么是不可能的. (2认同)
  • 我很难学到它.:P这是由我的教授验证的. (2认同)

Ste*_*non 5

  • 简介,不要推测.在知道要改变什么之前,不要改变该死的东西.

假设你得到一个配置文件,显示所有的数学运算真的让你失望:

  • 以往任何时候都pow(someFloat,2).编译器应该能够为您优化这一点,但通常,在较新的硬件上,这些优化可能尚未到位.这应该总是写成someFloat*someFloat.pow()函数通常是数学库中最昂贵的函数.简单乘法将始终至少与调用pow()一样快,并且始终至少同样准确(假设符合IEEE-754算术).此外,编译器更容易优化.
  • 当工作floatS IN C,使用数学库函数的后缀形式. sinf比...更快sin. sqrtf比...更快sqrt.除了功能本身更快,您可以避免不必要的转换double.
  • 如果您看到ARMv6处理器(不是3GS或新的iPod Touch)的速度减慢,请确保在进行大量浮点计算时不要编译拇指代码.拇指指令集(在thumb2之前)无法访问VFP寄存器,因此每个浮点运算都需要一个垫片.这可能非常昂贵.
  • 如果你只想将加速度矢量的长度减少1.0(提示:这不能达到你想要的效果),那么有更高效的算法可以做到这一点.