【问题标题】:bit test and set (BTS) on a tbb atomic variable对 tbb 原子变量进行位测试和设置 (BTS)
【发布时间】:2014-04-10 06:38:46
【问题描述】:

我想对一个 tbb 原子变量执行bitTestAndSet

atomic.h from tbb似乎没有任何位操作。

如果我将 tbb 原子变量视为普通指针并执行__sync_or_and_fetch gcc 编译器不允许这样做。

有解决办法吗?

相关问题:

assembly intrinsic for bit test and set (BTS)

【问题讨论】:

    标签: c++ c assembly tbb


    【解决方案1】:

    可以使用 compare_and_swap 循环,如下所示:

    // Atomically perform i|=j. Return previous value of i.
    int bitTestAndSet( tbb::atomic<int>& i, int j ) {
        int o = i;                  // Atomic read (o = "old value")
        while( (o|j)!=o ) {         // Loop exits if another thread sets the bits
            int k = o;
            o = i.compare_and_swap(k|j,k);
            if( o==k ) break;       // Successful swap
        }
        return o;
    }
    

    请注意,如果 while 条件在第一次尝试时成功,则将只有一个获取栅栏,而不是完整栅栏。这是否重要取决于上下文。

    如果存在高争用的风险,则应在循环中使用某种退避方案。 TBB 在内部使用类 atomic_backoff 进行争用管理,但它目前不是公共 TBB API 的一部分。

    还有第二种方法,如果不关心可移植性并且您愿意利用未记录的事实,即 tbb::atomic 和 T 的布局在 x86 平台上是相同的。在这种情况下,只需使用汇编代码对 tbb::atomic 进行操作。下面的程序演示了这种技术:

    #include <tbb/tbb.h>
    #include <cstdio>
    
    inline int SetBit(int array[], int bit) {
        int x=1, y=0;
        asm("bts %2,%0\ncmovc %3,%1" : "+m" (*array), "+r"(y) : "r" (bit), "r"(x));
        return y;
    }
    
    tbb::atomic<int> Flags;
    volatile int Result;
    
    int main() {
        for( int i=0; i<16; ++i ) {
            int k = i*i%32;
            std::printf("bit at %2d was %d.  Flags=%8x\n", k, SetBit((int*)&Flags,k), +Flags);
        }
    }
    

    【讨论】:

    • 感谢您的回答。我不希望位设置失败。如果我使用 CAS,它可能无法设置该位。我想盲目设置位
    • 位设置失败重试有什么区别?这就像线程稍后到达一样。并非所有硬件都具有原子位集。实际上,如果使用sync_or_and_fetch的结果,gcc会生成一个cmpxchg循环。我假设结果很有趣,因为问题标题是“测试和设置”,而不仅仅是“设置”。
    • 如果机器有硬件BTS指令,那它还会使用cmpxchg吗?
    • tbb::atomic 的布局与 T 的布局相同(即我们不会在对象中隐藏任何额外的机制。)因此,如果您使用BTS,并使用 reinterpret cast,您可以将其应用于 tbb::atomic.
    • BTS 理论上会更快,因为硬件仲裁逻辑会进行内容操作。而在 cmpxchg 循环中可能需要重试。但只有在高争用情况下,差异才会显着,而在高争用情况下,程序无论如何都可能表现不佳。
    猜你喜欢
    • 2014-05-23
    • 1970-01-01
    • 2017-08-03
    • 2010-12-25
    • 1970-01-01
    • 2012-06-22
    • 1970-01-01
    • 2011-09-02
    • 1970-01-01
    相关资源
    最近更新 更多