矢量加载/存储和聚集/分散的每个元素原子性?

2023-11-24

考虑一个像这样的数组atomic<int32_t> shared_array[]。如果你想要 SIMD 矢量化怎么办for(...) sum += shared_array[i].load(memory_order_relaxed)?。或者在数组中搜索第一个非零元素,或者将其范围归零?这可能很少见,但请考虑任何不允许元素内撕裂但元素之间重新排序的用例。(也许是寻找 CAS 候选人)。

I think x86 aligned vector loads/stores would be safe in practice to use on for SIMD with mo_relaxed operations, because any tearing will only happen at 8B boundaries at worst on current hardware (because that's what makes naturally-aligned 8B accesses atomic1). Unfortunately Intel's manuals only say:

“访问大于四字的数据的 x87 指令或 SSE 指令可以使用多个内存访问来实现。”

无法保证这些组件访问自然对齐、不重叠或其他任何情况。 (有趣的事实:x87 10 字节fld m80在 Haswell 上使用 2 个负载微指令和 2 个 ALU 微指令完成负载,根据阿格纳·福格的说法,大概是 qword + word。)

如果您想以一种面向未来的方式进行矢量化,当前的 x86 手册称该方式将适用于所有未来的 x86 CPU,您可以使用 8B 块加载/存储movq / movhps.

或者也许你可以使用 256bvpmaskmovd带着真实的面具,因为手册的操作部分将其定义为多个单独的 32 位负载,例如Load_32(mem + 4)。这是否意味着每个元素都充当单独的 32 位访问,保证该元素内的原子性?

(在真实的硬件上,Haswell 上有 1 个负载和 2 个 port5 uops,或者在 Ryzen 上只有 1 或 2 个负载 + ALU uops (128 / 256)。我认为这是针对不需要从以下元素中抑制异常的情况:进入未映射的页面,因为这可能会更慢(但我不知道它是否需要微码辅助)。无论如何,这告诉我们它至少与正常的原子一样vmovdqa在 Haswell 上加载,但这并没有告诉我们关于 x86 Deathstation 9000 的任何信息,其中 16B / 32B 向量访问被分解为单字节访问,因此每个元素内可能存在撕裂。

我认为实际上可以安全地假设您不会在 16、32 或 64 位元素中看到撕裂aligned矢量加载/存储在任何真正的 x86 CPU 上,因为这对于已经必须保持自然对齐的 64 位标量存储原子性的高效实现没有意义,但是了解手册中的保证实际上有多远很有趣.)


聚集 (AVX2,AVX512) / 分散 (AVX512)

指令如vpgatherdd更明显的是由多个单独的 32b 或 64b 访问组成。 AVX2 形式已记录就像做多个FETCH_32BITS(DATA_ADDR);因此,据推测,这已被通常的原子性保证所覆盖,并且如果每个元素不跨越边界,则将自动收集每个元素。

AVX512聚集记录在英特尔的 PDF insn 参考手册中 as
DEST[i+31:i] <- MEM[BASE_ADDR + SignExtend(VINDEX[i+31:i]) * SCALE + DISP]), 1)分别为每个元素。 (排序:元素可以按任何顺序收集,但故障必须按从右到左的顺序传递。其他指令的内存排序遵循 Intel- 64 内存排序模型。)

AVX512 scatters以相同的方式记录(上一个链接的第 1802 页)。没有提到原子性,但它们确实涵盖了一些有趣的极端情况:

  • 如果两个或多个目的地索引完全重叠,则可以跳过“较早”的写入。

  • 元素可以按任何顺序分散,但故障必须按从右到左的顺序传递

  • 如果该指令覆盖自身然后发生故障,则之前只能完成元素的子集 故障已传递(如上所述)。如果故障处理程序完成并尝试重新执行此操作 指令,将执行新指令,并且分散不会完成。

  • 仅保证对重叠向量索引的写入相对于彼此有序(从 LSB 到 源寄存器的 MSB)。请注意,这还包括部分重叠的向量索引。写的不是 重叠可以按任何顺序发生。其他指令的内存排序遵循 Intel-64 内存 订购型号。请注意,这并没有考虑映射到同一物理层的非重叠索引。 地址位置。

(即,因为相同的物理页被映射到两个不同虚拟地址的虚拟内存中。因此允许在地址转换之前(或与之并行)进行重叠检测,而无需在地址转换之后重新检查。)

我将最后两个纳入其中,是因为它们是有趣的极端案例,我什至没有想过要考虑。自我修改的案例很搞笑,但我认为rep stosd会有同样的问题(它也是可中断的,使用rcx跟踪进度)。

我认为原子性是 Intel-64 内存排序模型的一部分,因此他们提到它并且没有说任何其他内容的事实似乎暗示每个元素的访问是原子的。 (收集两个相邻的 4B 元素几乎肯定不算作一次 8B 访问。)


x86 手册保证哪些向量加载/存储指令在每个元素的基础上是原子的?

在真实硬件上进行的实验测试几乎肯定会告诉我,我的 Skylake CPU 上的一切都是原子的,但这不是这个问题的目的。我问我对手册的解释是否正确vmaskmov / vpmaskmov负载,以及收集/分散。

(如果有任何理由怀疑真正的硬件将继续是简单的元素原子原子movdqa负载,这也将是一个有用的答案。)


  1. 脚注:x86 原子性基础知识:

在 x86 中,8B 或更窄的自然对齐加载和存储保证是原子的,根据Intel和AMD手册。事实上,对于缓存访问,任何不跨越 8B 边界的访问也是原子的。 (在 Intel P6 及更高版本上,提供了比 AMD 更强的保证:缓存行(例如 64B)内未对齐对于缓存访问来说是原子的)。

16B 或更宽的向量加载/存储不保证是原子的。它们位于某些 CPU 上(至少对于当观察者是其他 CPU 时的缓存访问而言),但即使是对 L1D 缓存的 16B 宽原子访问也不会使其成为原子的。例如,AMD K10 Opterons 插槽之间的 HyperTransport 一致性协议在对齐的 16B 向量的两半之间引入撕裂,即使对同一套接字(物理 CPU)中的线程进行测试显示没有撕裂。

(如果您需要完整的 16B 原子加载或存储,您可以使用以下命令进行破解lock cmpxchg16b就像海湾合作委员会所做的那样std::atomic<T>,但那是terrible为了性能。也可以看看x86_64 上的原子双浮点或 SSE/AVX 矢量加载/存储.)


None

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

矢量加载/存储和聚集/分散的每个元素原子性? 的相关文章

随机推荐

  • 如何将数组从 Asp.net 服务器端传递到客户端的 Javascript 函数

    如何将在服务器端创建的数组传递到客户端以通过 Javascript 进行操作 任何伪代码都会有所帮助 您需要将其作为 JavaScript 数组声明嵌入到页面中 有多种方法可以做到这一点 但通常意味着将数组转换为写入页面的文本 可能使用 C
  • Swift 中的反向范围

    有没有办法在 Swift 中使用反向范围 例如 for i in 5 1 do something 是一个无限循环 在较新版本的 Swift 中 该代码可以编译 但在运行时会出现错误 致命错误 无法形成 upperBound 我知道我可以使
  • 如何在 iOS 14 Home Widget 中显示当前时间(实时)

    我正在为 ios 14 Home Widget 开发一个应用程序 在显示当前时间 数字时钟 时遇到一个问题 即该小部件没有每秒更新 众所周知 苹果不允许每秒触发时间线 有没有其他方法可以实时更新显示当前时间 我尝试了这些方法 但没有按预期工
  • 以编程方式访问 JPA

    是否可以访问其中的信息
  • 如何在 Istio 中设置 AWS ALB 而不是 ELB?

    我正在尝试在 Kubernetes AWS 中设置 ALB 负载均衡器而不是默认的 ELB 负载均衡器 负载均衡器必须连接到 istio ingressgateway 我寻找解决方案 只找到了one 但提到的 istio 版本是 V1 现在
  • Chartjs - 保持 2 个图表并排对齐

    杰斯小提琴 http jsfiddle net 8gvkmLxL 我有 2 个彼此相邻的条形图 我希望它们相对于 x 轴对齐 我很难实现这一点 因为图形高度根据标签的长度而变化 请参阅 jsfiddle 链接 保持实际图表高度一致性的最佳方
  • Typescript/Angular/ES6:我终于可以让 `hasOwnProperty()` 死在 for 循环中了吗?

    我一直不喜欢检查的必要性hasOwnProperty 当在 javascript 中循环对象时 for var key in object if object hasOwnProperty key continue Now I can do
  • 如何使用 Istio 创建内部网关?

    目前 我们成功设置 Istio 来创建几个入口网关 例如 api example com 和 app example com 将流量路由到具有目的地规则等的各种服务 除此之外 我们还愿意使用Istio 的功能仅限内部 API 但我们不确定如
  • 相当于内联输出参数声明?

    搜索了一下 找不到这个 我正在寻找 C 7 内联输出变量声明的 VB Net 等效项 例如 MethodCall arg1 out string arg2 等效的 VB Net 版本中是否存在这样的东西 恐怕重复的提议不太正确 但我已将海因
  • 如何在 iOS 上的 Swift 4 中以编程方式重新启动应用程序?

    我有问题 更改语言后 我想重新启动我的应用程序 所以我想收到一条带有文本 的警报消息 您想重新启动应用程序以更改语言吗 Yes No 如果用户按 是 我该如何重新启动应用程序 我的解决方案 let alertController UIAle
  • 在 TypeScript 中引用没有名称的类以在子类中使用不同的静态方法

    在 ES6 中 您可以通过以下方式引用静态方法this constructor class MainClass static info return This is some information constructor this inf
  • Android USB主机:异步中断传输

    我正在尝试连接 USB 设备 我自己构建 来与我的开发板 ODROID X 进行通信 不幸的是 就异步通信而言 例子很少 我在中断驱动的数据交换方面遇到了一些问题 如何使用异步中断模式建立连接 在一个方向上 传输是可能的 但在两个方向上都不
  • 控制相机纵向拍照不会旋转最终图像

    我试图控制 Android 相机在肖像应用程序中拍照 但当我保存照片时 它是横向的 我将图像旋转了 90 度setCameraDisplayOrientation 方法 但是不起作用 然后我找到了这个post但是TAG ORIENTATIO
  • T4 模板 - 适合生成 C++ 代码吗?

    是否存在任何问题可能导致 MS 的 T4 模板代码生成系统不适合生成 C 代码 答案有点长 但我想有些人可能会觉得有趣 我想说 T4 非常适合生成 C 有些人可能会反驳说 C 已经有了进行元编程的工具 例如 预处理器 使用预处理器和高阶宏
  • C99 'restrict' 关键字的实际用法?

    我正在浏览一些文档和问题 答案 并看到提到了它 我读了一个简短的描述 指出这基本上是程序员的承诺 指针不会被用来指向其他地方 谁能提供一些值得实际使用的实际案例 restrict表示指针是唯一访问底层对象的东西 它消除了指针别名的可能性 使
  • 什么是热观测值和冷观测值?

    我看了视频我知道一般原则 即使没有人订阅 热也会发生 冷会 按需 发生 此外 Publish 将冷数据转换为热数据 Defer 将热数据转换为冷数据 但我仍然觉得我错过了细节 以下是我想回答的一些问题 您能为这些术语给出一个全面的定义吗 在
  • 在线图像编辑器 - Ajax 还是 Flex / Flash?

    我正在制定一个计划 构建一个只有一些基本功能的在线图像编辑器 它 显然 应该包含一个画布工作区并支持以下功能 1 从您的计算机上传图像或提交链接2 调整图像大小 通过拖动角 3 旋转和翻转4 拖动 移动 平移5 分层 如果画布上有多个图像
  • 使绑定重定向适用于 Office 加载项

    我在 Word 插件中使用 Microsoft Bcl Async 我的插件被编译为 exe test addin exe 文件 该文件从 Microsoft Word 作为程序集加载 当我直接启动可执行文件时 一切正常 但是当我从 Wor
  • 一个或零到一实体框架代码优先 FluentApi

    我需要创建 Fluentapi 一对一或零对一引用 并在两个实体上都具有导航属性 实体二应包含存储外键的简单属性 实体 ID public class EntityOne public int Id get set public Entit
  • 矢量加载/存储和聚集/分散的每个元素原子性?

    考虑一个像这样的数组atomic