负载是否可以在获取操作下方滑动/存储是否可以漂浮在C++释放上方?
Can loads slip beneath an acquire operation / can stores float above a release in C++?
TL/DR:获取/发布操作是否只允许 4 次重新排序中的 1 次(而不是 2 次(?如果是这样,为什么?
目前,根据我对获取发布语义的理解,(基本上(
- 获取操作不允许其下方的负载/存储 浮动在其上方
- 释放操作不允许其上方的负载/存储滑入其下方
但关于相反方向的说法较少。
从一些来源(Jeff Preshing和其他人的博客,以及一些架构手册似乎暗示(我读到获取/释放操作相当于一个(给定内存位置上的原子操作+内存屏障(/(内存屏障+原子操作(。
他们描述了 4 种内存屏障,并说例如,获取操作使用类似于 LoadLoad + LoadStore 的屏障(以及类似的发布(。
据我了解,这些障碍(LoadLoad + LoadStore 和 StoreStore + LoadStore 相应地(只允许:
-
一家商店溜到收购之下
-
漂浮在释放装置上方的负载
负载不能滑到获取下方/商店不能漂浮在释放上方。
这通常是正确的吗?这对C++正确吗?C++与一般含义有什么不同吗?
(因为例如这个答案说负载可以滑到收购下方(据我所知(。我也有几个消息来源说,任何东西都可能溜到收购之下(反之亦然(。
如果这是正确的,那么这样做的理由是什么?我试图想出类似的东西(用于发布(:
x.store(5, std::memory_order_release);
y.store(true, std::memory_order_relaxed);
不同的线程以不同的顺序读取它们是一件坏事,因为它用于双重检查锁定等模式。
这接近一个原因吗?如果是这样,有人可以举出获取和释放的可靠例子吗?
虽然对于商店滑落在获取/负载浮动在释放上方,但(可能(没有这样的缺点......
内存屏障可用于实现加载获取和存储发布语义,但它们提供的保证比要求更严格,如 Jeff Preshing 的文章中所述:
请注意,这些障碍在技术上比 在单个内存上获取和发布语义需要什么 操作,但它们确实达到了预期的效果。
如果在加载获取和后续内存操作之间放置 LoadLoad + LoadStore 屏障,则无法在屏障之后按程序顺序对屏障之前的所有负载重新排序,并且所有以后的内存访问都无法在屏障之前重新排序。这比实现特定加载操作的获取语义更严格,因为屏障对所有以前的加载进行排序,而不仅仅是需要获取语义的特定负载。所以它们并不完全等同。商店发布语义也是如此。Herb Stutter对此发表了评论:
是的,这是我演示文稿中的一个错误(单词多于实际 幻灯片(。这个例子很好,但我应该修复"如果 这是一个释放围栏。特别:
从 1:10:30 开始,我说发布围栏存在正确性问题是不正确的,因为它允许商店漂浮起来(它确实如此( 不是,如前所述,该规则在 29.8.2 中;谢谢!– 我应该拥有的 说的是,这仍然是一个性能悲观,因为 围栏与该预期存储无关,但由于我们没有 知道它必须悲观地应用于所有以下商店 随后的普通存储,直到下一个适用的特殊内存 操作同步点 – 它经常将它们全部推低 不需要
根据 LoadLoad、LoadStore 和 StoreStore 屏障实现负载获取和存储发布语义的原因是 ISA 仅提供此类障碍。有研究建议使用更灵活或可配置的障碍,这些障碍可能仅适用于特定的内存操作或指令范围或块,但它们尚未进入任何ISA。
- 在函数范围内在堆栈上分配的数组在离开函数时是否总是被释放?
- COM :是否可以查看是否存在对我的某个 COM 对象的进程外引用?我可以释放它吗?
- 如果分配数组引发异常,是否应该释放该数组
- 是否可以使用分配器对象来释放另一个分配器分配的内存?
- 释放动态分配的内存时是否需要执行此额外步骤
- 如果包含映射的静态库与可执行文件和动态库链接,静态映射(变量)是否会被多次释放?
- 原子获取是否与互斥锁释放同步?
- 我是否需要在 c++ 中从本地指针中释放分配的内存?
- 我是否访问了已释放的内存,或者在这种情况下DrMemory报告不正确?
- 在不释放所有动态分配的资源的情况下结束程序是否有风险
- 如何知道指针是否已在其他地方释放
- c++ std map 的擦除功能是否释放了指针键的内存?
- 删除[]是否释放整个内存块
- 是否释放了局部变量的地址
- join() 是否释放了分配的内存?- C++11 线程
- nullptr是否释放指针的内存
- 对象的析构函数是否释放用于创建对象的指针所指向的内存?
- 将数组(int*)设置为NULL是否释放其占用的内存
- unordered_map::clear() 是否释放 C++ 中元素占用的内存
- Boost.Serialization 是否释放了在加载指针期间创建的内存