C++ 做C++;条件语句携带从条件表达式到语句的依赖关系?
我问的是记忆模型意义上的问题 我这样问是因为我想知道我是否可以在下面使用C++ 做C++;条件语句携带从条件表达式到语句的依赖关系?,c++,c++11,memory-model,C++,C++11,Memory Model,我问的是记忆模型意义上的问题 我这样问是因为我想知道我是否可以在下面使用std::memory\u order\u consume: MLOCALEMPTR1和2以及mAtomicMemPtr是指向共享缓冲区的指针 在制作线程中,我正在做: for (int x = 0; x < 10; ++x) { ++mLocalMemPtr1 *mLocalMemPtr1 = x; // <========= A mAtomicMemPtr.store(mL
std::memory\u order\u consume
:
MLOCALEMPTR1和2以及mAtomicMemPtr是指向共享缓冲区的指针
在制作线程中,我正在做:
for (int x = 0; x < 10; ++x)
{
++mLocalMemPtr1
*mLocalMemPtr1 = x; // <========= A
mAtomicMemPtr.store(mLocalMemPtr1, std::memory_order_release);
}
for(int x=0;x<10;++x)
{
++MLOCAMPTR1
*mLocalMemPtr1=x;//测试->doSomeLongRunningThing
我特别担心B
可能在A
之前执行。我知道我可以使用std::memory\u order\u acquire
,但我可以使用consume(更轻量级)如果条件语句导致内存顺序依赖。我认为,使用消费
顺序,编译器实际上可以提前复制整个mSharedBuffer
。您需要acquire
语义来使先前缓存的变量副本无效,而不是mAtomicMemLocPtr
.:
发布消费订单
如果线程A中的原子存储被标记为std::memory\u order\u release,线程B中来自同一变量的原子加载被标记为std::memory\u order\u consume,则所有内存写入(非原子和松弛原子)从线程A的角度来看,在原子存储之前排序的依赖项在线程B中会产生明显的副作用,也就是说,一旦原子加载完成,线程B保证看到线程A写入内存的所有内容,如果它将数据依赖项带入原子加载中
1.10.10:
如果满足以下条件,则评估A在评估B之前排序依赖关系
-A对原子对象M执行释放操作,在另一个线程中,B对M执行消耗操作,读取以A(…)为首的释放序列中由任何副作用写入的值
1.10.9:
如果-A的值用作B的操作数,则计算A与计算B具有相关性,除非:
-B是对std::kill_依赖项(29.3)的任何专门化的调用,或
-A是内置逻辑AND(&&,请参见5.14)或逻辑or(| |,请参见5.15)运算符的左操作数,或
-A是条件(?:,请参见5.16)运算符的左操作数,或
-A是内置逗号(,)运算符(5.18);(…)的左操作数
基于这些事实,我说应该同步mlocalemptr2
。但是仍然存在评估顺序的问题
if (atomic.load(std::consume) < x)
if(原子负载(标准::消耗)
首先计算哪一个是未指定的。无法保证(因为我在标准中找不到它)编译器将首先执行消耗操作,刷新共享缓冲区,然后加载原子,然后加载
未找到操作数在“期望”中求值的证明顺便说一句,如果没有对原子负载的显式分解,mlocalemptr2
,它将无法工作,CPU可能会读取mlocalemptr2
memory\u order\u acquire
指出的内存的陈旧值,在这里不会有太大变化,因为mlocalemptr2
带有数据依赖性正如在中所述,那么我要说
tempMemPtr = mAtomicMemPtr.load(std::memory_order_consume);
将依赖项带入循环的条件(将其视为布尔变量标志)。但该条件不会在任何循环体操作中作为操作数读取(也不会写入循环体中另一个操作读取的对象)。因此,需要一个acquire操作,以便使在发布之前排序的操作也发生在acquire之后的操作(即读写发布)之前,而不依赖于使用操作和循环体中的操作之间的数据依赖关系
可能涉及发布-消费语义的解决方案是:
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);
}
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);
}