[英]How to optimize math with 2D vectors?
我正在使用iOS應用程序,該應用程序使用數千個對象的數組執行一些計算。 這些對象具有具有x和y坐標的屬性,x和y軸的速度以及其他xy屬性。 有一些數學運算可以計算由數組中的對象表示的物理對象之間的交互。 數學非常簡單,基本上是計算施加到對象上的力,速度以及每個對象的位置(x,y)的變化。 我在Objective C中使用常規的標量數學編寫了代碼,在iPhone 5s上運行良好,但是在其他設備(如iPhone 4、4s,5和iPad mini)上運行太慢。 我發現最耗時的操作是計算兩點之間的距離以及計算向量的長度,如下所示,其中涉及到平方根:
float speed = sqrtf(self.dynamic.speed_x,2)+pow(self.dynamic.speed_y,2));
因此,我不得不做些事情以加快計算速度。 我重新編寫了代碼,以使具有對象坐標的屬性以及由X和Y分量表示的速度等屬性成為GLKVector2類型的向量。 我希望通過使用特殊的矢量函數(例如GLKVector2Distance,GLKVector2Normalize,GLKVector2Add等),可以更快地計算變量,例如2個矢量之間的距離(或點,按照我的理解),矢量的加法和減法。 ,這對性能沒有太大幫助,因為,正如我所相信的那樣,因為將具有GLKVector2類型的屬性的對象放到我不得不使用NSValue的數組中,以及將GLKVector2值從該對象中解碼回去,用於執行向量計算的數組。 下面是對象實現中計算方法的代碼:
GLKVector2 currentPosition;
[self.currentPosition getValue:¤tPosition];
GLKVector2 newPosition;
// calculations with vectors. Result is in newPosition.
self.currentPosition = [NSValue value:&newPosition withObjCType:@encode(GLKVector2)];
此外,當我重新編寫代碼以使用GLKVector2時,我收到了內存警告,並且在運行應用程序一段時間后有時會崩潰。
我花了幾天時間試圖找到一種更好的方法來更快地進行計算,我查看了vecLib,openGL,但沒有找到對我來說可以理解的解決方案。 我有一種感覺,我可能不得不看用C編寫代碼並將其以某種方式集成到目標C中,但是我不理解如何在不使用NSValue數千次的情況下將其與對象數組集成。
如果有人可以就我應該朝哪個方向提出建議,我將不勝感激。 也許有一些庫可以輕松地在Objective C中與存儲在數組中的對象組一起使用?
了解如何使用樂器。 除非您在更改前后測量速度,否則任何性能優化都是毫無意義的。 包含1000個對象的數組什么都不是,因此您可能不必擔心。 或減速完全不同。 使用儀器。
x * x是一個乘法。 powf(x,2.0)是一個昂貴的函數調用,可能需要20到100倍的時間。
GLKVector2是一個原語(它是一個並集)。 試圖將其存儲到NSValue中是完全沒有意義的,並且浪費的時間可能比直接存儲它要多100倍。
聽起來您遇到了兩個常見問題:1)使用高級語言進行快速數學運算,以及2)一個元問題:是否從他人的工作中受益(OpenGL, 以及此處列出的一些想法 )以開發者的陡峭學習曲線為交換。
特別是對於此主題,我認為使用圖書館的交易非常好。 對於許多人(例如Eigen )來說,大多數學習曲線都是關於Objective C和C ++的集成,您可以很快將其拋在腦后。
( distnaceSquared(a,b)
,通常,計算對象之間的距離的平方足以進行比較。如果在您的應用中有效,則可以通過用distnaceSquared(a,b)
替換distance(a,b)
來節省周期。
這是一個有關將物理計算與當前的Objective-C類集成在一起的問題的解答。 如果您的.m
文件中包含C代碼片段,則可能看起來像
static CGPoint point[MAX_OBJ];
static int n_points = 0;
如您建議的那樣,在普通C語言中具有相應的功能,用於模擬作用於point
物理交互以更新對象位置,如
void tick_world() {
for (int k = 0; k < n_points; k ++) {
float speed = sqrtf((point[k].x*point[k].x) + (point[k].y*point[k].y));
...
}
}
那么,你的Objective-C類Moving
的移動對象可能包含一個指向特定CGPoint
的point
,你會在接口(可能是相應的定義*.h
文件):
@interface Moving : NSObject {
...
CGPoint *pos;
}
處理init
消息時,您可以獲取並初始化point
的下一個可用元素。 如果您的對象在整個運行期間都持續存在,則可以通過以下方法非常簡單地完成此操作
@implementation
...
-(id)initAtX:(float)x0 Y:(float)y0 {
self = [super init];
if (self) {
if (n_points == MAX_OBJ) {
[self release];
return nil;
}
pos = point + n_points ++;
pos->x = x0;
pos->y = y0;
}
return self;
}
如果“ Moving
對象不能持久存在,則可能需要考慮一種在銷毀后回收插槽的明智方法。 例如,您可以使用NAN
初始化point
所有x
,並將其用作找到空閑插槽的方法。 在您的dealloc
,然后將pos->x = NAN
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.