어제 저는 빠른 스핀 록 작성 방법에 대해 this question을 게시했습니다. Cory Nelson 덕택에 제 질문에서 논의 된 다른 방법들보다 성능이 우수한 방법을 찾은 것 같습니다. CMPXCHG
명령을 사용하여 잠금이 0인지 무료인지 확인합니다. CMPXCHG
은 'BYTE', WORD
및 DWORD
에서 작동합니다. 나는 지시가 BYTE
에 더 빨리 작동한다고 가정 할 것이다. 하지만 데이터 유형의 각을 구현하는 잠금을 썼다 :WORD에 대한 cmpxchg가 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-포인터가 항상 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 개의 물리적 코어가있는 프로세서에서 다음 결과를 msec 단위로 측정했습니다.
1 thread 2 threads 4 threads
8-bit 200 700 3200
16-bit 200 500 1400
32-bit 200 900 3400
데이터가 모든 기능을 실행하는 동일한 시간이 걸릴 것을 시사한다. 그러나 여러 스레드가 확인해야 할 때 012 비트를 사용하여 lck == 0
은 상당히 빠를 수 있습니다. 왜 그런가요? 나는 그것이 lck
의 정렬과 관련이 있다고 가정하지 않습니까? 사전에
감사합니다.
'이것이 많은 차이는 아니지만 스핀 록은 많이 사용되는 개체입니다.'- 천국 30 년 이상의 멀티 스레드 소프트웨어 개발에서 단 하나의 소프트웨어를 명시 적으로 사용하지 않았습니다. –
'pause' 명령을 루프 외부가 아닌 스핀 루프 내부로 이동하십시오. 16 비트 인스 턴션은 여분의 0x66/0x67 접두사 바이트를 필요로합니다. 8 비트 또는 32 비트 명령어보다 약간 더 크고 느립니다. 따라서 여분의 오버 헤드로 인해 16 비트 경우의 경합을 줄이기 위해 루프가 느려질 수 있습니다. –
이러한 잠금으로 인해 임의의 손상이 발생하면 놀라지 않을 것입니다. ebx (호출 수신자 저장 레지스터)를 저장 및 복원하지 않고 호출자가 보존 할 것으로 기대하는 값을 손상시킬 수 있기 때문입니다. 대신 edx를 사용하십시오. –