2

C++ でより高速なメモリ アロケータを使用しようとしています。ライセンス/コストの関係で Hoard を使用できません。シングルスレッド設定で NEDMalloc を使用していて、優れたパフォーマンスが得られましたが、別のものに切り替える必要があるかどうか疑問に思っています-私が理解しているように、NEDMalloc は C ベースの malloc() & free() C++ ベースの new & delete 演算子 (私が頻繁に使用する) ではありません。

問題は、スレッドセーフにする必要があるため、(過剰なコピーを防ぐために) 参照カウントされるオブジェクトを malloc しようとしていますが、このオブジェクトにはミューテックス ポインターも含まれています。そうすれば、最後のコピーを削除しようとしている場合は、まずポインターをロックしてからオブジェクトを解放し、最後にミューテックスをロック解除して解放する必要があります。

ただし、malloc を使用して boost::mutex を作成することは不可能に見えます。コンストラクターを直接呼び出すことは禁止されているため、プライベート オブジェクトを初期化できないからです。

そのため、この奇妙な状況が残っています。 new を使用してロックを割り当て、 nedmalloc を使用して他のすべてを割り当てています。しかし、大量のメモリを割り当てると、割り当てエラーが発生します (nedmalloc の代わりに malloc に切り替えると消えます ~ しかし、パフォーマンスはひどいです)。私の推測では、これはメモリ内の断片化と、nedmalloc と new がナイスを並べて配置できないことが原因であると考えられます。

より良い解決策が必要です。何を提案しますか?

4

4 に答える 4

4

Google のmalloc 置換は非常に高速で、デフォルトでスレッド セーフであり、使いやすいです。アプリケーションにリンクするだけで、 or malloc/freeおよびnew/の動作が置き換えられますdelete。これにより、新しいアロケーターが実際に速度を上げていることを確認するためにアプリを再プロファイリングすることが特に簡単になります。

于 2010-06-14T16:55:02.267 に答える
2

グローバル演算子newandをオーバーロードして、使用しているanddeleteの新しいバージョンを呼び出すことができます。これにより、物事がうまく連携するようになるはずですが、これがまだ起こっていなかったとしたら驚くでしょう.mallocfree

ミューテックスの作成に関しては、placement new を使用します。これは、コンストラクターを手動で呼び出す方法です。の静的配列はchar、バッファ経由で行います。たとえば、グローバル:

static char buf[sizeof(Mutex)];
static Mutex *m=0;

次に、mポインターを初期化します。

m=new(buf) Mutex;

(必要に応じてポインターを揃えたり、変数の名前を変更したりすることもできます。)

注目すべきことの 1 つは、Mutexコンストラクター自体がより多くのメモリ割り当てを行う場合、これが問題になる可能性があることです。これは可能性は低いですが、可能です。(このようなまれなケースでは、割り当てを行わないクロスプラットフォームのミューテックス ラッパーのアドホックな実装には通常問題はありません。プラットフォーム タイプを直接使用して使用するだけ#ifdefです。どちらの場合もコードはそれほど多くなく、問題のシステムの経験がある人なら誰でも、関連するコードをバグなしで短時間で作成できます。)

この方法で作成されたオブジェクトを正しくクリーンアップするのは難しい場合があるため、気にしないことをお勧めします (いや、真剣に)。メモリ マネージャーを実装するために使用しているときに、このようなものがリークしてもまったく問題ありません。それについて怒っても意味がありません。(プロセス終了の概念を持つシステムで作業している場合、OS は基になるミューテックスをクリーンアップすることがほぼ保証されています。)

于 2010-06-14T17:00:17.140 に答える
1

通常、C++newdelete演算子は内部的に単純な C ライブラリ関数mallocを呼び出しますfree(さらに、ctors と dtors を呼び出すようないくつかの追加の魔法)。したがって、これらの関数のカスタム実装を提供するだけで十分な場合があります (これは組み込み C++ 開発ではまれではありませんが、いくつかのリンカが必要です)。 -レベルの作業)。どのシステムとどのコンパイラをターゲットにしていますか?

于 2010-06-14T16:57:08.993 に答える
1

実際のメモリ割り当てが、アロケータを置き換えることで有益な利益が得られるほど重大な問題であることをプロファイリングして検証しましたか?

NEDMalloc はスレッドセーフですか?

多くの場合、デフォルトの c++ の new/delete 演算子は、内部で malloc と free を使用して、コンストラクター/デストラクターを呼び出す前後に実際のメモリ割り当てを行います。特定の状況にない場合は、グローバルな new および delete 演算子をオーバーライドして、必要な割り当て実装を呼び出すことができます。これには、メモリが常に同じアロケータで割り当て/割り当て解除されるように注意する必要があります (特にライブラリを扱う場合)。

于 2010-06-14T16:53:51.767 に答える