3

私は並列アプリ(C、pthread)に取り組んでいます。ある時点で並列パフォーマンスが悪いため、システム コールをトレースしました。私のトレースは、私のプログラムがmprotect()何度も呼び出していることを示しました...私のプログラムを大幅に遅くするのに十分です。

私は大量のメモリを割り当てますが (を使用) 、ヒープ サイズを増やすためmalloc()の呼び出しは妥当な数しかありません。brk()では、なぜこれほど多くの呼び出しが行われるのmprotect()でしょうか?!

4

4 に答える 4

3

多くのスレッドを作成および破棄していますか?

ほとんどの pthread 実装は、スレッド スタックを割り当てるときに「ガード ページ」を追加します。これは、スタック オーバーフローを検出するために使用される、アクセス保護されたメモリ ページです。ガード ページを保護 (保護解除) するために、スレッドが作成または終了されるたびに、少なくとも 1 回は mprotect を呼び出す必要があります。この場合、いくつかの明らかな戦略があります。

  1. pthread_attr_setguardsize()スレッドを作成する前に、ガード ページ サイズをゼロに設定します。
  2. スレッドプールを使用します(プロセッサが言うほど多くのスレッドの)。スレッドがタスクを処理したら、スレッドを終了して新しいスレッドを作成するのではなく、プールに戻して新しいタスクを取得します。

別の説明としては、オーバーフローが検出された場合にスレッドのスタックが拡張されるプラットフォームを使用している可能性があります。これは GCC/Glibc を使用する Linux ではまだ実装されていないと思いますが、最近、これらの方針に沿った提案がいくつかありました。処理中に大量のスタック スペースを使用する場合は、 を使用して初期/最小スタック サイズを明示的に増やすことができますpthread_attr_setstacksize

または、それはまったく別のものかもしれません!

于 2009-05-12T02:39:14.530 に答える
2

mallocにptmalloc2があるglibcライブラリは、メインスレッド以外のスレッドのヒープのマイクロ管理にmprotect()を内部的に使用します(メインスレッドの場合、代わりにsbrk()が使用されます)。malloc()は、最初にmmap()を使用してメモリの大きなチャンクを割り当てます。ヒープ領域に競合があると思われる場合はスレッド。次に、不要な部分の保護ビットを変更して、mprotect()でアクセスできるようにします。後で、ヒープを拡張する必要がある場合は、mprotect()を使用して保護を読み取り/書き込み可能に再度変更します。これらのmprotect()呼び出しは、マルチスレッドアプリケーションでのヒープの拡大と縮小を目的としています。

http://www.blackhat.com/presentations/bh-usa-07/Ferguson/Whitepaper/bh-usa-07-ferguson-WP.pdf は、これをもう少し詳細に説明しています。

于 2011-10-10T19:27:22.200 に答える
2

可能であれば、デバッグ libc の下でプログラムを実行し、mprotect() で中断します。コール スタックを見て、mprotect() 呼び出しにつながるコードの動作を確認します。

于 2009-05-11T11:35:31.360 に答える
0

「valgrind」スイートには、「callgrind」と呼ばれるツールがあり、何が何を呼び出しているかがわかります。「callgrind」でアプリケーションを実行すると、結果のプロファイル データを「kcachegrind」で表示できます (「cachegrind」または「callgrind」によって作成されたプロファイルを分析できます)。次に、左側のペインで「mprotect」をダブルクリックすると、それを呼び出しているコードとその回数が表示されます。

于 2011-08-14T17:50:18.077 に答える