相关疑难解决方法(0)

为什么libc++的shared_ptr实现不将acq_rel fetch_sub拆分为release fetch_sub和acquire fence?

release()为了简单起见,libc++的shared_ptr实现可以描述为:

void release()
{
    if (ref_count.fetch_sub(1, std::memory_order_acq_rel) == 1)
    {
        delete this;
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么libc++不把它分成release decrement和acquisition fence呢?

void release()
{
    if (ref_count.fetch_sub(1, std::memory_order_release) == 1)
    {
        std::atomic_thread_fence(std::memory_order_acquire);
        delete this;
    }
}
Run Code Online (Sandbox Code Playgroud)

正如Boost 建议的那样,这看起来很优越,因为它不会对除最后一个减量之外的所有内容强加获取内存顺序。

c++ atomic shared-ptr memory-barriers libc++

7
推荐指数
0
解决办法
204
查看次数

C++ 11:memory_order_relaxed和memory_order_consume之间的区别

我现在正在学习C++ 11内存阶模型,并想明白之间的差别memory_order_relaxedmemory_order_consume.

具体而言,我正在寻找一个简单的例子,其中一个不能代替memory_order_consumememory_order_relaxed.

有一篇很好的文章详细阐述了一个memory_order_consume可以应用的简单但非常具有说明性的例子.下面是文字复制粘贴.

例:

atomic<int*> Guard(nullptr);
int Payload = 0;
Run Code Online (Sandbox Code Playgroud)

制片人:

Payload = 42;
Guard.store(&Payload, memory_order_release);
Run Code Online (Sandbox Code Playgroud)

消费者:

g = Guard.load(memory_order_consume);
if (g != nullptr)
    p = *g;
Run Code Online (Sandbox Code Playgroud)

我的问题包括两部分:

  1. 一个可取代memory_order_consumememory_order_relaxed在上面的例子?
  2. 一个可以建议类似的例子memory_order_consume不能被替换memory_order_relaxed

c++ memory-model c++11

6
推荐指数
2
解决办法
2746
查看次数

除了提供必要的保证外,硬件内存屏障是否可以更快地了解原子操作?

TL;DR:在生产者-消费者队列中,放置一个不必要的(从 C++ 内存模型的角度来看)内存栅栏或不必要的强内存顺序是否有必要以牺牲可能更差的吞吐量为代价来获得更好的延迟?


C++ 内存模型是在硬件上执行的,方法是使用某种内存栅栏来实现更强的内存顺序,而不是将它们放在较弱的内存顺序上。

特别是,如果生产者这样做store(memory_order_release),而消费者使用 观察存储的值load(memory_order_acquire),则加载和存储之间没有围栏。在 x86 上根本没有栅栏,在 ARM 上栅栏是在存储之前和加载之后进行放置操作。

没有围栏存储的值最终会被没有围栏的负载观察到(可能在几次不成功的尝试之后)

我想知道在队列的两侧放置围栏是否可以更快地观察到值?如果有围栏和没有围栏,延迟是多少?

我希望只有一个循环load(memory_order_acquire)pause/yield限制为数千次迭代是最好的选择,因为它无处不在,但想了解原因。

由于这个问题是关于硬件行为的,我希望没有通用的答案。如果是这样,我主要想知道 x86(x64 风格),其次是 ARM。


例子:

T queue[MAX_SIZE]

std::atomic<std::size_t>   shared_producer_index;

void producer()
{
   std::size_t private_producer_index = 0;

   for(;;)
   {
       private_producer_index++;  // Handling rollover and queue full omitted

       /* fill data */;

      shared_producer_index.store(
          private_producer_index, std::memory_order_release);
      // Maybe barrier here or stronger order above?
   }
}


void consumer()
{
   std::size_t private_consumer_index = 0;

   for(;;)
   {
       std::size_t observed_producer_index = shared_producer_index.load( …
Run Code Online (Sandbox Code Playgroud)

c++ x86 arm cpu-architecture memory-barriers

2
推荐指数
1
解决办法
192
查看次数