スピンロックとmutexの速度比較

スピンロック(spin lock)とは

ロックを取得できるまでループし続ける。そのためロックを取得できないとCPUを占有し続けるので、競合が多く発生する状況下では一般的なmutexに比べて不利になる。
ただしロックの確認作業はmutexより早い。
詳しくは: スピンロック - Wikipedia

Threading Building Block(TBB)でベンチを取る

では、実際にどれだけ早いのか試してみよう。
確認にはIntel Threading Building Block(TBB)を使用する。
TBBはOSSC++テンプレートを使用した並列処理ライブラリで、x86系 CPUに適した最適化がなされている。WindowsMac OS X他でも使えるがx86系CPUで使用できないのが惜しまれる。
Threading Building Blocks |

使用環境

Intel Celeron D 2.93GHz (残念ながらシングルコアである・・・)
Kernel 2.6.18-5-686
GCC 3.4.6
LIBC 2.3.6

プログラムコード
#include<stdio.h>
#include"tbb/task_scheduler_init.h"
#include"tbb/spin_mutex.h"
#include"tbb/mutex.h"
#include"tbb/tick_count.h"

using namespace tbb;

typedef spin_mutex benchmarked_mutex;

int main() {
  task_scheduler_init init;
  benchmarked_mutex mutex;

  tick_count t0 = tick_count::now();
  for(int i=0; i<10000000; i++) {
    benchmarked_mutex::scoped_lock lock(mutex);
  }
  tick_count t1 = tick_count::now();
  printf("time: %lf [s]\n",(t1-t0).seconds());

  return 0;
}
結果
何もしない場合 0.004576[s]
普通のmutex 0.815315[s]
spin_mutex 0.375953[s]
queuing_mutex 0.714402[s]
spin_rw_mutex 0.424482[s]
queuing_rw_mutex 0.836450[s]

2倍以上普通のmutexよりspinlockが早い事がわかる。尚、普通のmutexはOS依存mutexの事で、この場合pthread_mutexである。
競合が発生した場合のロスについては未調査なため、この結果のみで常にspinlockが速いとは言えないのに注意。またCPUによっての差異も今後調べていきたい。
ちなみにqueuing_mutexはロック順番どおりにロックを獲得できるmutexで、rwが付くものは後から読み取りロック、書き込みロックの指定ができるものである。

参考文献

インテル スレッディング・ビルディング・ブロック ―マルチコア時代のC++並列プログラミング

インテル スレッディング・ビルディング・ブロック ―マルチコア時代のC++並列プログラミング

一通り解説されてる。だけど時々訳が変。原文がおかしいのかもしれんが。。。