このチュートリアルに従って、VTUNE を使用してロックを解除する方法を理解しています。
このページでは、Vtune の結果を収集した後に次のように述べています。
最もホットなコード行を特定する
ホットスポット ナビゲーション ボタンをクリックして、最も待機時間がかかったコード行に移動します。インテル® VTune™ Amplifier は、draw_task 関数のクリティカルセクション rgb_critical_section に入る行 170 を強調表示します。draw_task 関数は、このコード行の実行中に約 27 秒間待機し、ほとんどの時間、プロセッサが十分に活用されていませんでした。この間、クリティカル セクションは 438 回競合しました。
rgb_critical セクションは、アプリケーションがシリアル化する場所です。各スレッドは、処理を続行する前に、クリティカル セクションが使用可能になるまで待機する必要があります。一度にクリティカル セクションに入れることができるスレッドは 1 つだけです。コードを最適化して、並行性を高める必要があります。
次のセクションに到達するまで、このチュートリアルに従うことができました:ロックを解除する
ロックを外す
マルチスレッド アクセスから計算を保護するために、rgb_critical_section が導入されました。簡単な分析は、コードがスレッド セーフであり、クリティカル セクションが実際には必要ないことを示しています。
私の質問は、コードがスレッドセーフであることをどのように確認するのですか?
示唆されているように、これらの行 (EnterCritical... と LeaveCritical...) にコメントしたところ、パフォーマンスが大幅に向上しましたが、なぜこのクリティカル セクションが不要なのかわかりませんでした。どの分析がこれを教えてくれますか?
関連するコードは、analyze_locks.cpp にあります。
public:
void operator () (const tbb::blocked_range <int> &r) const {
unsigned int serial = 1;
unsigned int mboxsize = sizeof(unsigned int)*(max_objectid() + 20);
unsigned int * local_mbox = (unsigned int *) alloca(mboxsize);
memset(local_mbox,0,mboxsize);
for (int y=r.begin(); y!=r.end(); ++y) {
drawing_area drawing(startx, totaly-y, stopx-startx, 1);
// Enter Critical Section to protect pixel calculation from multithreaded access (Needed?)
// EnterCriticalSection(&rgb_critical_section);
for (int x = startx; x < stopx; x++) {
color_t c = render_one_pixel (x, y, local_mbox, serial, startx, stopx, starty, stopy);
drawing.put_pixel(c);
}
// Exit from the critical section
// LeaveCriticalSection(&rgb_critical_section);
if(!video->next_frame()) tbb::task::self().cancel_group_execution();
}
}
draw_task () {}
};