标签: atomic

C++ 11原子内存排序 - 这是放宽(释放 - 消耗)排序的正确用法吗?

我最近使用std :: atomic三重缓冲区为C++ 11创建了一个端口,用作并发同步机制.这种线程同步方法背后的想法是,对于生产者 - 消费者情况,你有一个运行速度更快的生产者,消费者,三重缓冲可以带来一些好处,因为生产者线程不会因为必须等待而"减慢"速度对于消费者.在我的例子中,我有一个物理线程,在~120fps时更新,以及一个以~60fps运行的渲染线程.显然,我希望渲染线程始终能够获得最新状态,但我也知道我将从物理线程中跳过很多帧,因为速率不同.另一方面,我希望我的物理线程保持其不变的更新速率,而不受锁定我的数据的较慢渲染线程的限制.

最初的C代码是由remis-ideas制作的,完整的解释在他的博客中.我鼓励任何有兴趣阅读它的人进一步了解原始实现.

我的实现可以在这里找到.

基本思想是使一个具有3个位置(缓冲区)的数组和一个原子标志进行比较和交换,以定义在任何给定时间哪些数组元素对应于什么状态.这样,只有一个原子变量用于模拟数组的所有3个索引和三重缓冲背后的逻辑.缓冲区的3个位置被命名为Dirty,Clean和Snap.该生产商始终写入脏指数,以及可翻转作家交换肮脏与当前清洁指数.该消费者可以要求一个新的管理单元,其交换与清洁指数当前捕捉指数以获得最新的缓冲区.该消费者总是读取对齐位置的缓冲区.

该标志由8位无符号整数组成,这些位对应于:

(未使用)(新写入)(2x脏)(2x清洁)(2x快照)

newWrite extra bit标志由写入器设置并由读取器清除.读者可以使用它来检查自上次捕捉以来是否有任何写入,如果不是,则不会再次捕捉.可以使用简单的按位运算获得标志和索引.

现在好了代码:

template <typename T>
class TripleBuffer
{

public:

  TripleBuffer<T>();
  TripleBuffer<T>(const T& init);

  // non-copyable behavior
  TripleBuffer<T>(const TripleBuffer<T>&) = delete;
  TripleBuffer<T>& operator=(const TripleBuffer<T>&) = delete;

  T snap() const; // get the current snap to read
  void write(const T newT); // write a new value
  bool newSnap(); // swap to the latest value, if any
  void …
Run Code Online (Sandbox Code Playgroud)

c++ memory atomic compare-and-swap c++11

38
推荐指数
1
解决办法
2843
查看次数

原子x86指令的对齐要求

Microsoft提供了InterlockedCompareExchange执行原子比较和交换操作的功能.还有一个内在的._InterlockedCompareExchange

在x86上,这些是使用lock cmpxchg指令实现的.

但是,通过阅读这三种方法的文档,他们似乎并不同意对齐要求.

英特尔的参考手册没有说明对齐(除了如果启用了对齐检查并且进行了未对齐的内存引用,则会生成异常)

我也查找了lock前缀,具体说明了这一点

锁定前缀的完整性不会受到内存领域的对齐方式.

(强调我的)

所以英特尔似乎认为对齐是无关紧要的.无论如何,这个操作都是原子的.

_InterlockedCompareExchange固有的文档也只字未提对齐,但是InterlockedCompareExchange 功能指出,

该函数的参数必须在32位边界上对齐; 否则,该函数将在多处理器x86系统和任何非x86系统上表现不可预测.

什么给出了什么?对齐要求是否InterlockedCompareExchange只是为了确保该功能即使在cmpxchg指令不可用的486之前的CPU上也能正常工作?这看起来很可能基于上述信息,但在依赖它之前我想确定一下.:)

或者ISA需要对齐以保证原子性,我只是在英特尔的参考手册中找错了地方?

x86 winapi atomic interlocked memory-alignment

37
推荐指数
2
解决办法
5202
查看次数

AtomicInteger.incrementAndGet()与AtomicInteger.getAndIncrement()

当返回值不感兴趣时,当忽略返回值时,是否存在(AtomicInteger.getAndIncrement()和实际上不相关的)AtomicInteger.incrementAndGet()方法之间的差异?

我正在考虑哪些差异会更加惯用,以及哪些会减少CPU缓存的负载同步,或其他任何事情,任何事情来帮助决定哪一个比投掷硬币更合理地使用.

java atomic java.util.concurrent

37
推荐指数
4
解决办法
2万
查看次数

获取/发布与顺序一致的内存顺序

对于std::atomic<T>T是基本类型的任何地方:

如果我使用std::memory_order_acq_relfetch_xxx操作,以及std::memory_order_acquire用于load操作和std::memory_order_releasestore操作盲目(我的意思是,就像重置这些功能的默认内存排序)

  • 结果是否与我使用std::memory_order_seq_cst(用作默认值)的任何声明操作相同?
  • 如果结果相同,那么这种用法std::memory_order_seq_cst在效率方面是否与使用不同?

c++ concurrency atomic c++11

36
推荐指数
2
解决办法
8122
查看次数

如何自动更新最大值?

在串行代码中,更新最大值可以简单地通过

template<typename T>
void update_maximum(T& maximum_value, T const& value) noexcept
{
  if(value > maximum_value) maximum_value = value;
}
Run Code Online (Sandbox Code Playgroud)

但是,如何对atomic<T>保存最大值的变量执行此操作:

template<typename T>
void update_maximum(std::atomic<T>& maximum_value, T const& value) noexcept
{
   // want a lock-free, thread-safe implementation
}
Run Code Online (Sandbox Code Playgroud)

显然,串行版本的代码不起作用,因为另一个线程可能maximum_value在加载和存储之间发生变化.可以使用compare_exchange(比较==而不是>)来实现这个吗?怎么样?

请注意,不允许显式锁定(允许的唯一锁定是执行时可能出现的锁定std::atomic<T>).

c++ concurrency atomic max c++11

36
推荐指数
1
解决办法
6277
查看次数

原子地移动目录

我在同一个父目录中有两个目录.调用父目录和子目录alphabravo.我想用bravo替换alpha.最简单的方法是:

rm -rf alpha
mv bravo alpha
Run Code Online (Sandbox Code Playgroud)

mv命令是原子的,但rm -rf不是.在bash中有一种简单的方法可以用bravo原子替换alpha吗?如果没有,有复杂的方法吗?

附录:

如果目录在短时间内不存在,那么这不是一个不可逾越的问题.只有一个地方试图访问alpha,它会在做任何关键事情之前检查alpha是否存在.如果没有,它会给出错误消息.但如果有办法做到这一点会很好.:)也许有一些方法可以直接修改inode,或者某些东西......

linux bash atomic

35
推荐指数
7
解决办法
1万
查看次数

35
推荐指数
3
解决办法
1万
查看次数

Django嵌套事务 - "with transaction.atomic()"

我想知道我是否有这样的事情:

def functionA():
    with transaction.atomic():
        #save something
        functionB()

def functionB():
    with transaction.atomic():
        #save another thing
Run Code Online (Sandbox Code Playgroud)

有人知道会发生什么吗?如果functionB失败,functionA也会回滚吗?

谢谢!

django transactions nested atomic

35
推荐指数
1
解决办法
1万
查看次数

为什么std :: atomic <bool>比volatile bool慢得多?

多年来我一直在使用volatile bool进行线程执行控制,它工作正常

// in my class declaration
volatile bool stop_;

-----------------

// In the thread function
while (!stop_)
{
     do_things();
}
Run Code Online (Sandbox Code Playgroud)

现在,由于c ++ 11增加了对原子操作的支持,我决定尝试这样做

// in my class declaration
std::atomic<bool> stop_;

-----------------

// In the thread function
while (!stop_)
{
     do_things();
}
Run Code Online (Sandbox Code Playgroud)

但它比它快几个数量级volatile bool!

我编写的简单测试用例大约需要1秒才能完成volatile bool.随着std::atomic<bool>不过,我一直在等待约10分钟,并放弃了!

我试着用memory_order_relaxed旗帜loadstore同样的效果.

我的平台:Windows 7 64位MinGW gcc 4.6.x

我做错了什么?

UPD

是的,我知道volatile不会使变量线程安全.我的问题不是关于挥发性的,而是关于为什么原子是非常慢的.

UPD2 @all,感谢您的评论 - 我今晚到达机器后会尝试所有建议.

c++ performance multithreading atomic c++11

34
推荐指数
2
解决办法
3万
查看次数

33
推荐指数
7
解决办法
1万
查看次数