VC++ CriticalSectionの速度 【やってみた】


排他的制御を行いたい時に使うのがこのCiriticalSection(クリティカルセクション)。具体的にいつ使うのかというと、マルチスレッド処理などをしている時に、同時にアクセスされるとまずい部分(メモリ領域)がある場合に使う。

スポンサーリンク

例えば、2つスレッドがあった時、一方のスレッドで配列のサイズを変更し、もう片方のスレッドで同じ配列のある場所を読み込む場合、配列サイズ変更中にアクセスするとアクセス違反が発生し、場合によってはアプリケーションが落ちることがある。

WindowsでこのCriticalSectionを使う場合は、InitializeCriticalSection、EnterCriticalSection、LeaveCriticalSection、DeleteCriticalSectionという関数及びCRITICAL_SECTIONという構造体を利用する。具体的使い方などは、MSDNなどで調べてもらうとして、今回はこれを使った場合の実行速度を調べてみたいと思う。

速度

速度は、単純なforループとCriticalSection付のループで調べてみた。具体的なコードは以下の通り(ループ回数は、48kHzで1時間分、最適化は無効)

const int end = 60 * 60 * 48000;

for( int n = 0; n < end; n++ )
{
}

CRITICAL_SECTION CriticalSection;
::InitializeCriticalSection( &CriticalSection );

for( int n = 0; n < end; n++ )
{
	::EnterCriticalSection( &CriticalSection );
	::LeaveCriticalSection( &CriticalSection );
}

::DeleteCriticalSection( &CriticalSection );

Intel Core 2 Duoのマシンで測定してみたが、何もないループが、0.515106秒に対しクリティカルセクションでは7.089556秒となった。単純に考えた場合、1ループが14倍遅くなっている(このコストをどう考えるかだが、信号処理なら1サンプルごとの処理などにこれを使うには向いていないだろう)。

また、これらの関数は、同じスレッドから2度呼んでも正常に動作してくれる。これは、ロックカウントがあるためである。

for( int n = 0; n < end; n++ )
{
	::EnterCriticalSection( &CriticalSection );
	::EnterCriticalSection( &CriticalSection );
	::LeaveCriticalSection( &CriticalSection );
	::LeaveCriticalSection( &CriticalSection );
}

この場合の測定した時間は13.841430秒となり、さらに倍弱になってしまったことからCriticalSectionをなるべくかぶらせない努力は若干必要である。

スポンサーリンク
カテゴリー: やってみた   パーマリンク

コメントは受け付けていません。