GCC对读/写指令的重新排序

2024-02-29

Linux 的同步原语(自旋锁、互斥锁、RCU)使用内存屏障指令来强制内存访问指令重新排序。这种重新排序可以由 CPU 本身完成,也可以由编译器完成。

有人可以展示一些 GCC 生成的代码示例,其中完成了此类重新排序吗?我主要对 x86 感兴趣。我问这个问题的原因是为了了解 GCC 如何决定哪些指令可以重新排序。不同的 x86 mirco 架构(例如:sandybridge 与 ivybridge)使用不同的缓存架构。因此,我想知道 GCC 如何进行有效的重新排序,以帮助提高执行性能,而不管缓存架构如何。一些示例 C 代码和重新排序的 GCC 生成的代码将非常有用。谢谢!


GCC 可能执行的重新排序与 (x86) CPU 可能执行的重新排序无关。

让我们从编译器重新排序。 C语言规则是这样的:GCC禁止重排序volatile相互加载和存储内存访问,或删除它们,当它们之间出现序列点时(谢谢bobc https://stackoverflow.com/a/32536664/2809095对此进行澄清)。也就是说,在汇编输出中,这些内存访问将出现,并且将按照您指定的顺序精确排序。非-volatile另一方面,访问可以相对于所有其他访问重新排序,volatile或不,前提是(根据假设规则)计算的最终结果相同。

例如,一个非volatileC 代码中的加载可以按照代码所述多次执行,但顺序不同(例如,如果编译器认为在有更多寄存器可用时提前或稍后执行更方便)。它可以比代码所说的次数更少(例如,如果值的副本碰巧在大型表达式中间的寄存器中仍然可用)。或者它甚至可以被删除(例如,如果编译器可以证明加载是无用的,或者如果它将变量完全移动到寄存器中)。

为了防止编译器在其他时候重新排序,您必须使用特定于编译器的屏障。海湾合作委员会使用__asm__ __volatile__("":::"memory");以此目的。

这不同于CPU重新排序,又名内存排序模型。古代 CPU 严格按照指令在程序中出现的顺序执行指令;这就是所谓的节目排序, 或者强记忆排序模型。然而,现代 CPU 有时会通过“作弊”来提高运行速度削弱一点内存模型。

x86 CPU 削弱内存模型的方式记录在 Intel 软件开发人员手册,第 3 卷,第 8 章,第 8.2.2 节中“P6 及更新的处理器系列中的内存排序”。其部分内容如下:

  • 读取不会与其他读取重新排序。
  • 写入不会与较旧的读取重新排序。
  • 对内存的写入不会与其他写入重新排序,但[某些]例外。
  • 读取可以与对不同位置的较旧写入进行重新排序,但不能与对同一位置的较旧写入进行重新排序。
  • 读取或写入不能使用 I/O 指令、锁定指令或序列化指令重新排序。
  • 读取无法通过较早的 LFENCE 和 MFENCE 指令。
  • 写入无法传递较早的 LFENCE、SFENCE 和 MFENCE 指令。
  • LFENCE 指令无法传递较早的读取。
  • SFENCE 指令无法传递较早的写入。
  • MFENCE 指令无法传递较早的读取或写入。

它还在第 8.2.3 节中提供了非常好的示例,说明哪些内容可以重新排序,哪些内容不可以重新排序“说明内存排序原则的示例”.

正如您所看到的,使用 FENCE 指令来防止 x86 CPU 不恰当地重新排序内存访问。

最后,您可能感兴趣this http://preshing.com/20120625/memory-ordering-at-compile-time/链接,其中包含更多详细信息,并附带您渴望的组装示例。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GCC对读/写指令的重新排序 的相关文章

  • 强制jvm返回本机内存[重复]

    这个问题在这里已经有答案了 我时不时地运行需要大量内存的 eclipse 任务 因此 当任务运行时 jvm 会消耗大约 2 3GB 的 RAM 这是可以的 但是一旦 jvm 占用了该内存 它就不会释放它 并且我遇到了一种情况 堆中已用内存约
  • GCC:数组类型具有不完整的元素类型

    我已经宣布了struct 我尝试传递这些结构的数组 以及double双精度数组和一个整数 到一个函数中 我得到一个 数组类型具有不完整的元素类型 当我编译它时来自 gcc 的消息 我在通过考试的过程中犯了什么错误struct到函数 type
  • 使用Intel的PIN工具来计算程序中缓存命中/未命中的次数

    我一直在尝试编写一个 pintool 来检测给定程序中的缓存命中和未命中情况 我发现有INS IsMemoryRead Write等调用来判断指令是否是LD ST 有没有办法确定指令是否命中或未命中缓存 如果是这样 是否还可以获得从缓存 内
  • 将 mmap 内核启动参数保留的内存映射到用户空间

    正如中所讨论的this https stackoverflow com q 1911473 143897问题 我在启动时使用内核启动参数保留一个内存块memmap 8G 64G 我写了一个字符驱动程序 http pete akeo ie 2
  • 内存不一致与线程交错有何不同?

    我正在编写一个多线程程序 正在研究是否应该使用volatile对于我的布尔标志 关于并发性的文档 oracle Trail 没有解释任何关于memory consistency errors以外 当不同的线程有内存一致性错误时 就会发生内存
  • 了解 U-Boot 内存占用

    我不明白加载 U Boot 时 RAM 中发生了什么 我正在开发 Xilinx Zynq ZC702 评估套件 并尝试使用 U Boot 在其上加载 Linux 内核 于是我使用Xilinx工具Vivado和SDK生成了一个BOOT bin
  • 错误:“uint16_t”未声明? [复制]

    这个问题在这里已经有答案了 我有代码 include
  • 当结构体包含字符串时为其分配内存

    假设如果我有一个这样的结构 struct node note that i have changed the struct code according to my convenience char lastname char employ
  • 操作系统什么时候清除进程的内存

    进程在某些操作系统上成功或异常终止 操作系统何时决定擦除分配给该进程的内存 数据 代码等 在退出时或当它想为新进程分配内存时 这个清除内存分配过程在所有操作系统 winXP Win7 linux Mac 上都相同吗 据我了解 页表具有该进程
  • 带有适用于 MS-Windows 的工具链的预构建 MIPS 交叉编译器

    我在我的 Linux 机器上使用 MIPS 交叉编译器 效果很好 现在我需要在 Windows 上编译相同的应用程序 我正在网上搜索一些适用于 MS Windows 的预构建 MIPS 交叉编译器 带有工具链 但没有成功 由于我不确定该怎么
  • gcc 中 -g 选项的作用是什么

    我看到很多关于 gdb 的教程要求在编译 c 程序时使用 g 选项 我无法理解 g 选项的实际作用 它使编译器将调试信息添加到生成的二进制文件中 此信息允许调试器将代码中的指令与源代码文件和行号相关联 拥有调试符号可以使某些类型的调试 例如
  • 在 python 中将变量设置为“None”是否更节省内存?

    这是一个简单的问题 但由于我没有找到任何答案 我认为答案是否定的 但是 为了确保这一点 我要问 将变量设置为是否会使Python代码更有效None当我们在函数中使用完它们之后 举个例子 def foo fname temp 1 temp 2
  • 就 size_t 而言,“目标平台上最大可能对象的大小”是多少

    我正在阅读有关的文章size t在 C C 中http web archive org web 20081006073410 http www embedded com columns programmingpointers 2009001
  • 在 /dev/input/eventX 中写入事件需要哪些命令?

    我正在开发一个android需要将触摸事件发送到 dev input eventX 的应用程序 我知道C执行此类操作的代码结构如下 struct input event struct timeval time unsigned short
  • C99 中数组的静态大小[重复]

    这个问题在这里已经有答案了 一个非常简单的 C 程序 include
  • 包括带有大量全局变量的 C 头文件

    我有一个包含 100 多个全局变量的包含文件 它正在库中使用 但我链接库的一些程序也需要访问全局变量 它的构建方式 In one library c file define Extern In the programs that use t
  • 跟踪 Linux 程序中活跃使用的内存

    我想跟踪各种程序在特定状态下接触了多少内存 例如 假设我有一个图形程序 最小化时 它可能会使用更少的内存 因为它不会重新绘制窗口 这需要读取图像和字体并执行大量库函数 这些对象仍然可以在内存中访问 但实际上并没有被使用 类似的工具top它们
  • c# 通过内存地址调用方法

    我正在尝试在 C 中的指定内存地址调用函数 以下是我在 C 中的操作方法 typedef void do int i auto doActor do 0xAAAABEEF doActor 1 如果可能的话 如何在 C 中复制这种行为 对 C
  • 赋值运算符和复制构造函数有什么区别?

    我不明白C 中赋值构造函数和复制构造函数之间的区别 是这样的 class A public A cout lt lt A A lt lt endl The copy constructor A a b The assignment cons
  • iOS 视图控制器内存在被关闭后未释放

    当用户单击按钮时 它会显示一个带有两个视图控制器的新选项卡栏视图控制器 我是这样做的 ACLevelDownloadController dvc ACLevelDownloadController alloc initWithNibName

随机推荐

  • 如何提高索贝尔边缘检测器的效率

    我正在写一个计算机视觉库 https github com RoadKillCat PiCamVision从头开始使用 Python 来使用rpi相机 目前 我已经实现了转换为greyscale以及其他一些基本的img在我的设备上运行速度相
  • 如何创建适合移动设备的响应式菜单?

    我是 HTML CSS 新手 我正在尝试制作简单的响应式菜单 调整大小后 将显示浏览器菜单图标 然后单击打开菜单 请检查下面的代码 您能帮我吗 注意 我不想使用引导程序 body margin 0 padding 0 height 100
  • jquery 1.5 模拟 ajax

    在 jquery 1 5 中 模拟 ajax 请求的推荐方法是什么 是使用ajax扩展传输吗 http api jquery com extending ajax Transports http api jquery com extendi
  • 允许在数据库项目中删除(一次)列

    我想在现有表中删除一列 当我简单地从表的创建脚本中删除它时 它将在部署时导致错误 数据丢失 我想允许 在这种情况下 列删除 你会怎么做 要禁用数据丢失错误 单击架构比较文件中的选项图标 取消选中 阻止可能的数据丢失 该设置将仅针对 1 次架
  • 如何使用 ControlsFX 实现自动完成文本字段

    我正在使用 ControlsFX 的最新版本 8 0 5 我想我需要一些关于自动完成文本字段的帮助 因为我对此很陌生 我从这里得到了这个代码here https bitbucket org controlsfx controlsfx pul
  • Android Tabhost 问题 - .setIndicator

    首先让我澄清一下 我已经提到了与 Android TAbhost 相关的问题 我已经用谷歌搜索了 Android Tabhost 但未能找到解决方案 我的问题是 如果有 有什么方法可以将标题文本 即指示器 放入选项卡中 我认为问题的根源在于
  • 允许访问 C++ 中的容器对象

    我有一个像下面这样的课程 class Foo private std map
  • Play Framework 2.2.1 - 不区分大小写的路由

    我是 Play 新手 目前正在使用 Play 2 2 1 我正在尝试为 路由 中定义的端点实现不区分大小写的路由 例如我在路线文件中定义了一条路线 例如 accessLicense 如下所示 GET accessLicense contro
  • Django-firebird 无法工作

    我下载了该文件夹并将其放入C Python27 Lib site packages django contrib gis db backends firebird 但是当我使用它时 给我一个 error django core except
  • 如何在Python中删除两个numpy数组的重复元素

    我有两个数组命名 u v 例如 u np array 1 0 2 0 2 0 3 0 4 0 v np array 10 0 21 0 18 0 30 0 40 0 a np array 100 0 210 0 220 0 300 0 40
  • 单元测试 mocha Visual Studio Code 描述未定义

    如果我在控制台中运行 测试运行良好 mocha require ts node register tests spec ts 注意 我安装了 mocha 和 mocha g 我想从 Visual Studio Code 运行单元测试 启动
  • 如何拆分 CSV 行,使 row[0] 为名称,其余项目为元组?

    我有一个 csv 文件 其中第一列是棒球运动员的姓名 文件中的每个后续项目都是统计数据 我希望能够导入该文件 以便玩家名称等于统计数据的元组 现在 当我使用以下代码导入文件时 Orioles file Orioles csv rU for
  • Android,使可滚动视图溢出到左侧而不是右侧?

    建议我使用父视图在 TextView 中进行水平滚动
  • 如何使用 ngFor 和 bootstrap 4 创建新的一行卡片

    我正在尝试将 Bootstrap 4 的卡组功能与 Angular 一起使用ngFor 这是我现在的 HTML 但我找不到如何在插入 3 个项目后换行 div class row card group div class col 4 car
  • 附加进程时提升删除 Managed_shared_memory

    我有 2 个进程 进程 1 创建一个 boost Managed shared memory 段 进程 2 打开该段 然后进程 1 重新启动 进程 1 的启动如下 struct vshm remove vshm remove boost i
  • Zend Framework 2 - 分页

    如何获取控制器操作中的页面详细信息 我使用了专辑的分页 iteratorAdapter new Zend Paginator Adapter Iterator this gt getAlbumTable gt fetchAll pagina
  • 如何清理(防止SQL注入)SQL Server中的动态SQL?

    我们有大量依赖动态 SQL 的 SQL Server 存储过程 存储过程的参数在动态 SQL 语句中使用 我们需要在这些存储过程中使用标准验证函数来验证这些参数并防止 SQL 注入 假设我们有这些约束 我们无法重写过程以不使用动态 SQL
  • 不同语言如何在其标准库中实现排序? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何使用similar_text()改进PHP字符串匹配?

    我正在使用 PHP 的imilar text 调用来比较两个字符串 但是 我没有得到足够好的结果 例如 对于我希望看到 100 的匹配 我得到的最好结果是 80 95 我还可以使用哪些其他函数来深入了解字符串的核心
  • GCC对读/写指令的重新排序

    Linux 的同步原语 自旋锁 互斥锁 RCU 使用内存屏障指令来强制内存访问指令重新排序 这种重新排序可以由 CPU 本身完成 也可以由编译器完成 有人可以展示一些 GCC 生成的代码示例 其中完成了此类重新排序吗 我主要对 x86 感兴