2

メインスレッドで継続的なシミュレーションを実行するマルチスレッド VC++ (Windows) プログラムに取り組んでいます。このシミュレーションでは、同じスレッドまたはローダー スレッドで作成されるオブジェクトを使用します (両方の場合があります)。削除する場合も同様です。

これを行ったのは、非常に大きなオブジェクト (他の多くのオブジェクトで構成されている) が動的にロードおよびアンロードされる間、メイン スレッドがブロックされないようにするためです。これは基本的に機能しました。ただし、(たとえば) アンローダー スレッドが次々とオブジェクトを継続的に削除している間、他のスレッドの new および delete 呼び出しには時間がかかります。これは、内部スレッド保護が原因のようです。

私の次の動きは、これらの多くの小さなオブジェクトをプールすることによって、新規/削除の呼び出しの数を減らすことでした。そこで、プリミティブ メモリ マネージャーを作成しました。マネージャーは、malloc() を使用して 320 MB のバッファーを割り当て、64 バイトのブロックを使用してプログラムの他の部分に割り当て機能を提供します。ここで、placement new を使用して小さなオブジェクトを作成します。マネージャーの alloc/free メソッドは完全にミューテックス (ロック) で保護されています。

現在起こっていることは、マルチスレッド環境で正しく機能しないということです。カスタム管理オブジェクトの変更は無視されます。何が起こるかというと、バッファ全体が単一の変数として表示されるため、読み取り/書き込みデータの競合があってはならないということです。これは事実ですか?

ご想像のとおり、まったく別のオブジェクトが作成/削除されている間に 1 つのオブジェクトへのアクセスを制限するという選択肢はありません。では、このような状況ではどのような方法で行けばよいのでしょうか?

4

2 に答える 2

2

newsとsはdelete、単一のWindowsヒープオブジェクトに内部的に同期しています。

私が知っている最善の解決策は、HeapCreate HeapAllocHeapFreeを直接使用して、アロケータースレッドごとに1つのヒープオブジェクトを作成し、毎回HEAP_NO_SERIALIZEを指定することです。

割り当てられたスレッドが解放されたスレッドであることを確認する必要があります。つまり、割り当てたヘルパースレッドに「メモリを戻す」必要があります。

于 2013-02-19T12:39:46.193 に答える
0

これは事実ですか?

いいえ、そうは思いません。すべてのメモリは、連続したアドレス空間です。CPU は変数を認識せず、ページ、キャッシュ ライン、およびバイトのみを操作します。

考えられる原因: メモリ マネージャーのバグ。割り当てられたオブジェクトが互いにオーバーラップしている可能性があります。または、スレッドの同期に失敗した可能性があります (ところで、ミューテックスをクリティカル セクションに置き換える必要があります。便利なワッパーについては、CComAutoCriticalSection および CComCritSecLock ATL クラスを参照してください。短い操作の場合、それらは桁違いに高速に動作します)。ミューテックスより)。

考えられる原因: オブジェクトのバグ。おそらく、オブジェクトはそのアドレスの後に余分なバイトを書き込みますが、ヒープは割り当てサイズを丸めたので、各オブジェクトが new 演算子によって使用される HeapAlloc win32 API で割り当てられたときに問題なく動作します。

考えられる原因: メモリ アラインメントの問題。割り当てているオブジェクトのアドレスを少なくとも 8 に揃えてみてください。

于 2013-02-19T12:12:14.373 に答える