在忙碌等待螺旋锁时花费的CPU周期

时间:2015-08-17 13:22:45

标签: c++ c++11 spinlock

到目前为止,我有一个很棒的自旋锁,可以作为意图:

    std::atomic_flag barrier = ATOMIC_FLAG_INIT;

    inline void lock( ){
        while( barrier
            .test_and_set( std::memory_order_acquire ) )
                {}
    }

但是我想知道(指示性地)在其中花费了多少CPU周期(如果忙等待太长可能我会考虑一个至少让等待线程进入睡眠状态的互斥锁):

    inline void lock( int & waitCounter){
        while( barrier
            .test_and_set( std::memory_order_acquire ) )
                waitCounter++;
    }

当然这并没有统计锁定指令本身,所以我应该通过哪个常量来增加waitCounter以获得在忙等待中花费的周期的精确概念(我认为指令不会因为内存屏障而被流水线化所以计数在理论上非常精确)?

waitCounter+=2;
waitCounter+=3;
waitCounter+=4; //...

2 个答案:

答案 0 :(得分:1)

自旋锁所需的周期数取决于许多因素,包括同时尝试执行自旋锁的线程数。

我最近对此进行了测试here

简短的回答:由于您可以直接控制的事物(应用程序代码)和您无法控制的事情(总线争用),它可能会有很大差异。最低周期数和最大周期之间的关系可以是110到950或更高。

答案 1 :(得分:0)

至少GCC with -O4似乎是函数

inline void lock( int & waitCounter){
    while( barrier
        .test_and_set( std::memory_order_acquire ) )
            waitCounter+=5;
    waitCounter+=2;

归结为一个代码,该代码保留了自己使用的指令数

.L5:
    add DWORD PTR [rdi], 5
.L3:
    mov eax, edx
    xchg    al, BYTE PTR barrier[rip]

    test    al, al
    jne .L5
    add DWORD PTR [rdi], 2
    ret

这远不是一个完整的答案,但可能会给出这个想法。