0

単純な振り子をシミュレートするための有限差分法を使用して、物理プロジェクトのモデリング クラスを実装しようとしています。このクラスを可能な限りジェネリックにして、メソッドの反復ごとに値を使ってやりたいことを何でもできるようにしたいと考えています。このため、必要に応じてメソッドを停止するためにも使用できるコールバック ブロックをメソッドに与えました。

たとえば、オイラー メソッドのループは次のようになります。

for (NSInteger i = 0; i < n; i++) {

    if (callBack) {
        if(!callBack(NO, currentTheta, currentThetaDot, currentT, (CGFloat)i/n)) break;
    }

    currentTheta += self.dt*f_single_theta(currentThetaDot);
    currentThetaDot += self.dt*f_single_thetaDot(currentTheta, currentThetaDot, gamma);

    currentT += self.dt;

}

そしてcallBackブロックでコードを実行します

^BOOL (BOOL complete, double theta, double thetaDot, CGFloat timeElapsed, CGFloat percentComplete){

    eulerT = [eulerT stringByAppendingFormat:@"%.8f\n",timeElapsed];
    eulerTheta = [eulerTheta stringByAppendingFormat:@"%.8f\n",theta];

    if ((currentThetaDot*currentThetaDot + cos(currentTheta)) > 0.5) {
        return 0; // stops running if total E > 0.5
    }        

    return 1;

}];

eulerT と eulerTheta は、後でファイルに保存する文字列です。このコールバック メソッドを使用すると、すぐに大量のメモリが蓄積されます。n が 10,000 のオーダーであっても、約 1Gb の RAM が使用されます。ブロックの呼び出しをコメントアウトするとすぐに、これはすぐにcallBack削除されます。とにかく、大規模なメモリの問題なしにこの優れた機能を維持できるでしょうか?

4

2 に答える 2

2

Objective C を初めて使用する多くの人は、 と の違いを理解していませ[NSArray array][[NSArray alloc] init]。ARC が登場する前の時代には、その違いは今ではもっと明白でした。どちらも新しいオブジェクトを作成しますが、前者はオブジェクトを割り当てて現在の に割り当てNSAutoreleasePool、保持カウント 0 のままにし、後者はオブジェクトを割り当てて保持カウント 1 のままにします。

に割り当てられているオブジェクトはNSAutoreleasePool、保持カウントが 0 に達してもすぐには割り当て解除されません。代わりに、OS が時間を取得したときに割り当てが解除されます。一般に、これは制御が現在の実行ループに戻ったときと想定できますが、 でdrainが呼び出されたときでもありますNSAutoreleasePool

ARC を使用すると、違いはそれほど明白ではありませんが、それでも重要です。割り当てたオブジェクトのほとんどではないにしても、多くは自動解放プールに割り当てられます。つまり、使い終わったからといって元に戻すことはできません。これにより、投稿したもののように、タイトなループでメモリ使用量が急増します。解決策は、次のように自動解放プールを明示的に排出することです。

for (NSInteger i = 0; i < n; i++) {

    if (callBack) {
        @autoreleasepool {
            if(!callBack(NO, currentTheta, currentThetaDot, currentT, (CGFloat)i/n))
                break;
        }
    }

    currentTheta += self.dt*f_single_theta(currentThetaDot);
    currentThetaDot += self.dt*f_single_thetaDot(currentTheta, currentThetaDot, gamma);

    currentT += self.dt;

}
于 2013-11-09T04:04:42.910 に答える
2

ループの内側を @autoreleasepool{} でラップして、一時オブジェクトをクリーンアップする必要があります。

于 2013-11-09T01:10:39.507 に答える