昨日、高速スピンロックの書き方についてこの質問を投稿しました。Cory Nelsonのおかげで、私の質問で説明した他の方法よりも優れた方法を見つけたようです。この命令を使用してCMPXCHG
、ロックが0であり、それによって解放されているかどうかを確認します。CMPXCHG
「BYTE」で動作しWORD
ますDWORD
。命令はでより速く動作すると思いBYTE
ます。しかし、私は各データ型を実装するロックを作成しました。
inline void spin_lock_8(char* lck)
{
__asm
{
mov ebx, lck ;move lck pointer into ebx
xor cl, cl ;set CL to 0
inc cl ;increment CL to 1
pause ;
spin_loop:
xor al, al ;set AL to 0
lock cmpxchg byte ptr [ebx], cl ;compare AL to CL. If equal ZF is set and CL is loaded into address pointed to by ebx
jnz spin_loop ;jump to spin_loop if ZF
}
}
inline void spin_lock_16(short* lck)
{
__asm
{
mov ebx, lck
xor cx, cx
inc cx
pause
spin_loop:
xor ax, ax
lock cmpxchg word ptr [ebx], cx
jnz spin_loop
}
}
inline void spin_lock_32(int* lck)
{
__asm
{
mov ebx, lck
xor ecx, ecx
inc ecx
pause
spin_loop:
xor eax, eax
lock cmpxchg dword ptr [ebx], ecx
jnz spin_loop
}
}
inline spin_unlock(<anyType>* lck)
{
__asm
{
mov ebx, lck
mov <byte/word/dword> ptr [ebx], 0
}
}
次に、次の擬似コードを使用してロックをテストしました(lcm-pointerは常に4で割り切れるアドレスを指すことに注意してください)。
<int/short/char>* lck;
threadFunc()
{
loop 10,000,000 times
{
spin_lock_8/16/32 (lck);
spin_unlock(lck);
}
}
main()
{
lck = (char/short/int*)_aligned_malloc(4, 4);//Ensures memory alignment
start 1 thread running threadFunc and measure time;
start 2 threads running threadFunc and measure time;
start 4 threads running threadFunc and measure time;
_aligned_free(lck);
}
4つのスレッドを実行できる2つの物理コアを備えたプロセッサ(Ivy Bridge)で、ミリ秒単位で測定された次の結果が得られました。
1 thread 2 threads 4 threads
8-bit 200 700 3200
16-bit 200 500 1400
32-bit 200 900 3400
データは、すべての関数の実行に同じ時間がかかることを示しています。ただし、複数のスレッドlck == 0
で16ビットを使用するかどうかを確認する必要がある場合は、大幅に高速化できます。何故ですか?lck
私はそれが?の配置と関係があるとは思いません。
前もって感謝します。