c++条件语句是否带有从条件表达式到语句的依赖关系?
Do C++ conditional statements carry a dependency from the condition expression to the statement?
我特别从内存模型的角度提出这个问题。http://en.cppreference.com/w/cpp/atomic/memory_order
我问是因为我想知道我是否可以在下面使用std::memory_order_consume
:
mLocalMemPtr1和2和mAtomicMemPtr是指向共享缓冲区的指针。
在一个producer线程中,我正在做:
for (int x = 0; x < 10; ++x)
{
++mLocalMemPtr1
*mLocalMemPtr1 = x; // <========= A
mAtomicMemPtr.store(mLocalMemPtr1, std::memory_order_release);
}
在消费者中:
tempMemPtr = mAtomicMemPtr.load(std::memory_order_consume);
while (tempMemPtr != mLocalMemPtr2)
{
++mLocalMemPtr2;
int test = *mLocalMemPtr2; // <======== B
doSomeLongRunningThing(test);
tempMemPtr = mAtomicMemPtr.load(std::memory_order_consume);
}
所以依赖链去tempMemPtr -> mLocalMemPtr2 ->测试-> doSomeLongRunningThing?
我特别担心B
可能在A
之前执行。我知道我可以使用std::memory_order_acquire
,但是如果条件语句导致内存顺序依赖,我可以使用consume(这是更轻量级的)。
CppReference:
Release-Consume订购
如果线程A中的原子存储标记为std::memory_order_release,线程B中来自同一变量的原子加载标记为std::memory_order_consume,那么从线程A的角度来看,所有依赖顺序在原子存储之前的内存写入(非原子和宽松原子)在线程B中都成为可见的副作用,也就是说,一旦原子加载完成,如果线程B 在原子加载中携带了数据依赖项,则线程B保证看到线程A写入内存的所有内容。
1.10.10:
如果
,则求值A在求值B之前是依赖顺序的- A对原子对象M执行释放操作,在另一个线程中,B对M执行消费操作,读取由A(…)开头的释放序列中的任何副作用写的值
1.10.9:
基于这些事实,我说如果A的值被用作B的操作数,则计算值A携带对计算值B的依赖,除非:
- B是std::kill_dependency(29.3)的任何特化的调用,或者
—A是内置逻辑与(&&,见5.14)或逻辑或(||,见5.15)操作符的左操作数,或
—A是条件(?:,参见5.16)操作符,或
—A是内置逗号(,)操作符(5.18)的左操作数;(…)
mLocalMemPtr2
应该同步。然而,仍然存在一个求值顺序的问题。
if (atomic.load(std::consume) < x)
先计算哪一个是未指定的。不保证(因为我在标准中找不到它)编译器将首先执行消费操作,刷新共享缓冲区,然后加载atomic
,然后加载 x
。
没有找到在"希望"中求值的操作数的证明;如果没有显式分解原子负载mLocalMemPtr2
,它将无法工作,CPU可能会读取由mLocalMemPtr2
指向的内存的陈旧值。memory_order_acquire
在这里不会改变太多,因为mLocalMemPtr2
携带了一个数据依赖项。
我相信通过consume
排序,编译器实际上可以提前复制整个mSharedBuffer
。您需要acquire
语义来使以前缓存的除mAtomicMemLocPtr
以外的变量副本无效.
如果从字面上理解它们在carry依赖中所陈述的内容。那么我会说
tempMemPtr = mAtomicMemPtr.load(std::memory_order_consume);
将依赖项带入循环的条件(将其视为布尔变量标志)。但是,在任何循环体操作中,该条件都不会作为操作数被读取(也不会写入由循环体中的另一个操作读取的对象)。所以我们需要一个获取操作来让在释放之前被排序的操作也发生在获取之后的操作之前(读和写释放)而不依赖于消费操作和循环体中操作之间的数据依赖关系
可能包含发布消费语义的解决方案是:
tempMemPtr = mAtomicMemPtr.load(std::memory_order_consume);
while (tempMemPtr != mLocalMemPtr2)
{
mLocalMemPtr2 = tempMemPtr; // that line adds the dependency needed
++mLocalMemPtr2;
int test = *mLocalMemPtr2;
doSomeLongRunningThing(test);
tempMemPtr = mAtomicMemPtr.load(std::memory_order_consume);
}
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 如何编写一个使用n倍三元条件语句的C++布尔函数
- 如果条件不相关,我应该更喜欢两个 if 语句而不是 if-else 语句吗?
- 在 if 语句中使用 GetKeyState 时,它会跳过条件
- C++ 中的"if"语句不会从左到右计算条件
- 优化/减少 if 语句中的条件表达式
- CPP 带有条件语句的内在事物
- 有没有办法在循环中的条件至少满足一次时运行语句?
- 如果验证容器的大小并在同一条件语句下访问元素,这是很好的做法吗?
- 如果语句错误地读取字符串,则始终在第一个条件返回
- 条件不变的 if 语句会减慢我的C++代码吗?
- C++ - 这个条件语句写得正确吗?还是有更有效的写法?
- C++17 if 语句,带有初始值设定项但没有条件
- if语句中满足的条件的索引
- C++:如何在 if 语句条件中使用指针
- 在 CPP 中将函数调用定时为 if 语句条件
- c++ 读取左 IF 语句条件和右语句条件
- C++忽略if语句条件
- 考虑到模板参数,正在更改if语句条件
- IF语句条件内的循环