本文介绍了如何在C ++中以原子方式添加和获取128位数字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Linux x86_64和clang 3.3。

I use Linux x86_64 and clang 3.3.

这在理论上是可能的吗?

Is this even possible in theory?

std :: atomic< __ int128_t> 不工作(未定义的对某些函数的引用)。

std::atomic<__int128_t> doesn't work (undefined references to some functions).

也不工作('错误:无法编译此原子库调用')。

__atomic_add_fetch also doesn't work ('error: cannot compile this atomic library call yet').

两个 std :: atomic __ atomic_add_fetch 使用64位数字。

Both std::atomic and __atomic_add_fetch work with 64-bit numbers.

推荐答案

不可能用单个指令这样做,但你可以模拟它,仍然是无锁。除了最早的AMD64 CPU,x64支持 CMPXCHG16B 指令。有了一个多精度的数学,你可以很容易做到。

It's not possible to do this with a single instruction, but you can emulate it and still be lock-free. Except for the very earliest AMD64 CPUs, x64 supports the CMPXCHG16B instruction. With a little multi-precision math, you can do this pretty easily.

恐怕我不知道instrinsic for CMPXCHG16B 在GCC,但希望你得到一个旋转循环 CMPXCHG16B 的想法。这里是一些未经测试的VC ++代码:

I'm afraid I don't know the instrinsic for CMPXCHG16B in GCC, but hopefully you get the idea of having a spin loop of CMPXCHG16B. Here's some untested code for VC++:

// atomically adds 128-bit src to dst, with src getting the old dst.
void fetch_add_128b(uint64_t *dst, uint64_t* src)
{
    uint64_t srclo, srchi, olddst[2], exchlo, exchhi;

    srchi = src[0];
    srclo = src[1];
    olddst[0] = dst[0];
    olddst[1] = dst[1];

    do
    {
        exchlo = srclo + olddst[1];
        exchhi = srchi + olddst[0] + (exchlo < srclo); // add and carry
    }
    while(!_InterlockedCompareExchange128((long long*)dst,
                                          exchhi, exchlo,
                                          (long long*)olddst));

    src[0] = olddst[0];
    src[1] = olddst[1];
}

编辑:这里有一些未经测试的代码我可以找到对于GCC内在函数:

here's some untested code going off of what I could find for the GCC intrinsics:

// atomically adds 128-bit src to dst, returning the old dst.
__uint128_t fetch_add_128b(__uint128_t *dst, __uint128_t src)
{
    __uint128_t dstval, olddst;

    dstval = *dst;

    do
    {
        olddst = dstval;
        dstval = __sync_val_compare_and_swap(dst, dstval, dstval + src);
    }
    while(dstval != olddst);

    return dstval;
}

这篇关于如何在C ++中以原子方式添加和获取128位数字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-22 05:04