0

私は C++ でベイジアン推論サンプラーを開発しています。これは多くのことをツリー上で中継します。このツリーはスマート ポインター (Boost の shared_ptr と weak_ptr) の助けを借りて実装されています。

推論中 (つまり、長い C++ 関数を 1 ~ 2 分間実行している間)、ツリーは大幅に変更され、多くのノードが作成および破棄されます。

推論プロセス全体 (100% の負荷) がプロセッサ (より正確には 1 つのスレッド) を占有します。何らかの理由で新しいメモリ (新しいノード用) が占有されていますが、古いメモリが完全に解放されていないため、1 ~ 2 分間の推論後にメモリ オーバーフローが発生します。

ただし、推論プロセスに一時停止を追加すると、プログラムが古いオブジェクトを完全に破棄し、すべて正常に動作するように見えます。

その理由は、何らかの理由でデストラクタ (または、より正確には、その後に何が起こるか、つまりメモリの解放) が遅れているためだと私には思えます。

教えてください: 1) 本当に問題があるように見えますか? 2) はいの場合、「十分なメモリ」が解放されるまで待つ方がよい方法はありますか? 標準戦略とは何ですか?

(プログラムは Unix で実行されています。)

4

3 に答える 3

2

あなたが観察したメモリの問題は、C++ 自体にあるようには見えません。shared_ptr がメモリを解放する場合、何らかの遅れた方法ではなく、すぐに解放します。ただし、オペレーティング システムの都合により、「実際の」リリースがしばらく遅れる場合があります。Windows の「タスク マネージャー」などのプログラムでは、プログラムがますます多くのメモリを消費しているように見えるかもしれませんが、それは OS が予約しているメモリであり、実際には占有していません。計算が非常に大きなプロセッサ負荷を生成する場合、スケジューラは、計算などのより重要なことを邪魔しないように、時間があるまでかなり「重要でない」タスク (メモリの解放など) を遅らせる可能性があります。

ただし、メモリの解放と割り当てにはコストがかかります。そして、多くのメモリを交換可能に解放して割り当てているようです。独自のメモリ管理 (メモリ プールなど) を行うか、オブジェクト (つまりノード) 自体をリサイクルすることによって、そのメモリをリサイクルすることを検討する必要があります。新しい値でそれらをリセットします。どちらも shared_ptr と組み合わせて実行できます。

于 2013-01-22T09:37:46.687 に答える
1

ツリーにサイクルがあるように聞こえます。つまりshared_ptr、子ポインターと親ポインターの両方に使用され、ツリーノードの自動破壊を防ぎます。プレーンなポインターを使用する方がよい場合があります。

于 2013-01-22T09:46:05.823 に答える
0

オブジェクトを指す最後の shared_ptr が破棄されると、オブジェクトはすぐに削除されます。そのため、得られるものは非常に奇妙に聞こえます。私が想像できる唯一の考えは、ガベージコレクターを実装にアタッチしたことです...そうでない場合は、すべての古いオブジェクトが破棄されることを再確認してください。

于 2013-01-22T09:32:30.307 に答える