昨天我发布了有关如何编写快速自旋锁的this question。多亏了Cory Nelson,我似乎找到了一种方法,该方法优于我在问题中讨论的其他方法。我使用CMPXCHG指令检查锁是否为0,从而是否为空闲。 CMPXCHG适用于“BYTE”,WORDDWORD。我假设该指令将在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);
}

在具有2个能够运行4个线程的物理内核的处理器(Ivy Bridge)上,我获得了以下结果(以毫秒为单位)。
           1 thread    2 threads     4 threads
8-bit      200         700           3200
16-bit     200         500           1400
32-bit     200         900           3400

数据表明,所有功能需要花费相同的时间来执行。但是当多个线程必须检查使用16位的lck == 0是否可以显着更快时。这是为什么?我不认为这与lck的对齐有关吗?

提前致谢。

最佳答案

从我记得的情况来看,锁只适用于一个字(2个字节)。最初在486中引入时是这样写的。

如果您携带一个不同大小的锁,它实际上会产生2个锁的等效值(双字的锁字A和字B)。对于一个字节,它可能必须防止第二个字节的锁,这有点相似到2个锁...

因此,您的结果与CPU优化保持一致。

10-08 09:29