当前位置: 首页 > 知识库问答 >
问题:

x86获取语义获取和增量?

范浩荡
2023-03-14

假设我有一个时间戳计数器。

 static uint32_t _Atomic timestamp = 0U;

 static inline uint32_t get_ts(void) {
       return atomic_fetch_add_explicit(&timestamp, 1, memory_order_acquire);
 }

假设我有一些并发代码,我想通过实验测试和记录内存重新排序。

 for (;;) {
     uint32_t ts1 = get_ts();
     struct result result_a = do_a();

     uint32_t ts2 = get_ts();
     struct result result_b = do_b();

     log(ts1, &result_a);
     log(ts2, &result_b);
  }

在c11内存模型下,do\u a可能会被重新排序,超过get\u ts,使用do\u b()。

 for (;;) {
     uint32_t ts1 = get_ts();
     uint32_t ts2 = get_ts();
     struct result result_b = do_b();
     struct result result_a = do_a();

     log(ts1, &result_a);
     log(ts2, &result_b);
  }

但是,假设编译器没有在x86上重新排序锁xadd,则会阻碍所有加载和存储。因此,事实上x86(但不是编译器)不可能进行这种重新排序,因为get\ts调用充当了一个获取释放界限。

在x86上有没有办法实现真正的acquire语义获取和增量?

共有2个答案

解阳泽
2023-03-14

fetch\u add的“lock xadd”实现中有什么不真实?

如果您的意思是不希望锁定的RWM op提供的完整屏障具有更强的语义,那么在x86上您确实没有任何其他选择。对于加载,普通加载MOV指令确实提供了这种意义上的“true”获取语义,因为由于存储缓冲,在MOV之前按程序顺序执行的存储可能会被它之后的其他CPU观察到。

高泳
2023-03-14

是否允许编译器重新排序do_ado_b取决于这些html" target="_blank">函数的作用。原子优化是可能的[1],但受C11标准[草稿]第5.1.2.4节的约束。(我相信这是相关的。)

站点cppreference.com提供了关于该主题的重新措辞视图,包括memory_order_acquirememory_order_release的语义学定义。
带有获取语义学的加载和带有发布语义学的存储可以实现为:

Acquire load                       Release store
Load                               #StoreStore
#LoadLoad                          #LoadStore
#LoadStore                         Store

其中#表示栅栏(内存屏障)
然而,“英特尔内存排序”白皮书明确指出,加载、存储和加载存储重新排序从不在临时加载/存储上执行<因此,发布获取语义在x86上是免费的。

这不是使用像lock xadd这样的锁定(从而序列化)指令的问题;释放-获取语义学总是受到尊重——即使是简单的mov指令。
请注意,获取语义学与在获取加载之前执行的存储无关;它命令存储并在它之后加载。

至于你的最后一个问题,有点不清楚。

在x86上有没有办法实现真正的acquire语义获取和增量?

序列化所有指令的实现已经获得了语义学。在这方面,x86不做任何重新排序。

如果你的意思是,有没有办法让原子操作不顺序一致(在C11的意思中),那么答案是否定的。
您可以在英特尔手册中找到相关部分,但也可以在上面链接的白皮书中找到它。它说:

通过要求原子RMW(读-修改-写)操作,您还可以对原子变量强制执行顺序一致的顺序。

 类似资料:
  • 我正在尝试探索在测试中添加咆哮通知的功能。这允许在测试执行时将消息添加到屏幕上。 我正在尝试通过以下步骤指定的这种方法:http://elementalselenium.com/tips/53-growl 机器:windows 10 Selenium版本:2.53浏览器:Firefox 49 以下是我正在使用的脚本: 执行此操作时,我收到以下错误: 等待弹出窗口出现..单击弹出窗口..现在等待通知

  • 我正在阅读n3485中定义的C内存模型,它讨论了释放/获取语义,根据我的理解,以及本博客中给出的定义: Acquire语义是一个属性,它只能应用于从共享内存读取的操作,无论是读-修改-写操作还是普通加载。然后,该操作被视为读取获取。Acquire语义可以防止读Acquire的内存重新排序,并按照程序顺序执行读或写操作。 释放语义学是一个属性,它只适用于写入共享内存的操作,无论它们是读-修改-写操作

  • 问题内容: 我正在将Linux与x86(准确地说是64位)配合使用。有没有一种方法可以获取当前指令的地址。实际上,我想编写自己的简化版本 setjmp /longjmp 。,R ..发布了 longjmp 的简化版本。任何想法如何实现 setjmp 。简化版本,不考虑异常和信号等。 问题答案: 我相信只要使用64位代码即可。 32位习惯用法是:

  • 我们使用nextjs/reactjs作为FE,并且我们有一个server.js文件,它允许我们在上传映像,但是由于某种原因,每当我们运行服务器时,都会出现错误 下面是我们在server.js上的代码 这些是我们package.json中包含的脚本 希望得到一些答案和建议。这些代码在本地运行,没有任何问题

  • 英文原文: http://emberjs.com/guides/getting-ember/index/ Ember构建 Ember的发布管理团队针对Ember和Ember Data维护了不同的发布方法。 频道 最新的Ember和Ember Data的 Release,Beta 和 Canary 构建可以在这里找到。每一个频道都提供了一个开发版、最小化版和生产版。更多关于不同频道的信息可以查看博客

  • 问题内容: 我正在使用Expressjs版本4.我在req.param上得到了’undefined’。这是我的示例:app.js ./routes/新 newdata.html 我也尝试了和,但答案仍然相同。 问题答案: 引用路径中的变量。 帖子数据可以通过以下方式引用 假设您正在使用中间件。 然后是那些。 您可以使用上面的3种。外观上的顺序是,,。