使用 SIMD 内在函数时这些额外的反汇编指令是什么?

2023-11-23

我正在测试使用 SIMD 指令与 RyuJIT 可以获得什么样的加速,并且我看到了一些我不期望的反汇编指令。我的代码基于这篇博文来自 RyuJIT 团队的 Kevin Frei 以及相关帖子here。这是函数:

static void AddPointwiseSimd(float[] a, float[] b) {
    int simdLength = Vector<float>.Count;
    int i = 0;
    for (i = 0; i < a.Length - simdLength; i += simdLength) {
        Vector<float> va = new Vector<float>(a, i);
        Vector<float> vb = new Vector<float>(b, i);
        va += vb;
        va.CopyTo(a, i);
    }
}

我正在查询的反汇编部分将数组值复制到Vector<float>。大多数反汇编与 Kevin 和 Sasha 的帖子中的类似,但我强调了一些额外的指令(以及我混淆的注释),这些指令没有出现在他们的反汇编中:

;// Vector<float> va = new Vector<float>(a, i);
  cmp eax,r8d              ; <-- Unexpected - Compare a.Length to i?
  jae 00007FFB17DB6D5F     ; <-- Unexpected - Jump to range check failure
  lea r10d,[rax+3] 
  cmp r10d,r8d 
  jae 00007FFB17DB6D5F 
  mov r11,rcx              ; <-- Unexpected - Extra register copy?
  movups xmm0,xmmword ptr [r11+rax*4+10h  ]

;// Vector<float> vb = new Vector<float>(b, i);
  cmp eax,r9d              ; <-- Unexpected - Compare b.Length to i?
  jae 00007FFB17DB6D5F     ; <-- Unexpected - Jump to range check failure
  cmp r10d,r9d 
  jae 00007FFB17DB6D5F 
  movups xmm1,xmmword ptr [rdx+rax*4+10h]

请注意,循环范围检查符合预期:

;// for (i = 0; i < a.Length - simdLength; i += simdLength) {
  add eax,4  
  cmp r9d,eax  
  jg loop

所以我不知道为什么有额外的比较eax。谁能解释一下为什么我会看到这些额外的说明以及是否可以删除它们。

如果它与项目设置有关,我有一个非常相似的项目,显示相同的问题在 github 上 (see FloatSimdProcessor.HwAcceleratedSumInPlace() or UShortSimdProcessor.HwAcceleratedSumInPlaceUnchecked()).


我将注释一下我看到的代码生成,对于像Haswell这样支持AVX2的处理器,它可以一次移动8个浮点数:

00007FFA1ECD4E20  push        rsi
00007FFA1ECD4E21  sub         rsp,20h  

00007FFA1ECD4E25  xor         eax,eax                       ; i = 0
00007FFA1ECD4E27  mov         r8d,dword ptr [rcx+8]         ; a.Length
00007FFA1ECD4E2B  lea         r9d,[r8-8]                    ; a.Length - simdLength
00007FFA1ECD4E2F  test        r9d,r9d                       ; if (i >= a.Length - simdLength)
00007FFA1ECD4E32  jle         00007FFA1ECD4E75              ; then skip loop 

00007FFA1ECD4E34  mov         r10d,dword ptr [rdx+8]        ; b.Length
00007FFA1ECD4E38  cmp         eax,r8d                       ; if (i >= a.Length)
00007FFA1ECD4E3B  jae         00007FFA1ECD4E7B              ; then OutOfRangeException
00007FFA1ECD4E3D  lea         r11d,[rax+7]                  ; i+7
00007FFA1ECD4E41  cmp         r11d,r8d                      ; if (i+7 >= a.Length)
00007FFA1ECD4E44  jae         00007FFA1ECD4E7B              ; then OutOfRangeException

00007FFA1ECD4E46  mov         rsi,rcx                       ; move a[i..i+7]
00007FFA1ECD4E49  vmovupd     ymm0,ymmword ptr [rsi+rax*4+10h]  

00007FFA1ECD4E50  cmp         eax,r10d                      ; same as above 
00007FFA1ECD4E53  jae         00007FFA1ECD4E7B              ; but for b
00007FFA1ECD4E55  cmp         r11d,r10d  
00007FFA1ECD4E58  jae         00007FFA1ECD4E7B  
00007FFA1ECD4E5A  vmovupd     ymm1,ymmword ptr [rdx+rax*4+10h]  

00007FFA1ECD4E61  vaddps      ymm0,ymm0,ymm1                ; a[i..] + b[i...]
00007FFA1ECD4E66  vmovupd     ymmword ptr [rsi+rax*4+10h],ymm0  

00007FFA1ECD4E6D  add         eax,8                         ; i += 8
00007FFA1ECD4E70  cmp         r9d,eax                       ; if (i < a.Length)
00007FFA1ECD4E73  jg          00007FFA1ECD4E38              ; then loop

00007FFA1ECD4E75  add         rsp,20h  
00007FFA1ECD4E79  pop         rsi  
00007FFA1ECD4E7A  ret  

所以 eax 比较的是博客文章中提到的那些“讨厌的绑定检查”。该博客文章提供了一个尚未实际实现的优化版本,实际代码现在检查同时移动的 8 个浮点数的第一个和最后一个索引。博客文章的评论“希望我们能够充分加强边界检查消除工作”是一项未完成的任务:)

The mov rsi,rcx博客文章中也出现了指令,并且似乎是寄存器分配器中的限制。可能是受RCX作为一个重要寄存器的影响,它通常存储this。我假设,寄存器到寄存器的移动需要 0 个周期,因为它们只影响寄存器重命名,所以这对于完成此优化工作来说并不重要。

请注意 SSE2 和 AVX2 之间的差异是多么丑陋,虽然代码一次移动并添加 8 个浮点数,但它实际上只使用了其中的 4 个。Vector<float>.Count不管处理器的风格如何,都是 4,剩下 2 倍的性能。我想很难隐藏实现细节。

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

使用 SIMD 内在函数时这些额外的反汇编指令是什么? 的相关文章

  • OpenGL缓冲区更新[重复]

    这个问题在这里已经有答案了 目前我正在编写一个模拟水的程序 以下是我所做的步骤 创建水面 平面 创建VAO 创建顶点缓冲区对象 在其中存储法线和顶点 将指针绑定到此 VBO 创建索引缓冲区对象 然后我使用 glDrawElements 渲染
  • 如何使用 C# 以编程方式编辑 Power BI Desktop 文档参数或数据源?

    我有一个在 Power BI Desktop 中内置的报告模板 并保存为 pbix 或 pbit 文件 该模板使用DirectQuery SQL数据库作为数据源 而服务器地址和数据库名称被提取到参数中 还有一个参数包含一个ReportId
  • 如何调整 Windows 窗体以适应任何屏幕分辨率?

    我知道这是重复的问题 但我检查了所有其他相关问题 他们的答案没有帮助 结果仍然与屏幕截图 2 中所示相同 我是 C Windows 窗体新手 如截图1所示 我有Form1有一些控件 每组控件都放在一个面板中 我在 PC1 中设计了应用程序
  • 具有多个谓词的 C++11 算法

    功能如std find if来自algorithmheader 确实很有用 但对我来说 一个严重的限制是我只能为每次调用使用 1 个谓词count if 例如给定一个像这样的容器std vector我想同时应用相同的迭代find if 多个
  • make_shared<>() 中的 WKWYL 优化是否会给某些多线程应用程序带来惩罚?

    前几天我偶然看到这个非常有趣的演示 http channel9 msdn com Events GoingNative GoingNative 2012 STL11 Magic Secrets作者 Stephan T Lavavej 其中提
  • C# Winforms Designer 无法打开,因为它无法在同一程序集中找到类型

    我收到以下错误 找不到类型 My Special UserControl 请确保引用包含此类型的程序集 如果此类型是您的开发项目的一部分 请确保已使用当前平台或任何 CPU 的设置成功构建该项目 但没有任何意义的是My Special Us
  • 关闭整数的最右边设置位

    我只需要关闭最右边的设置位即可 我的方法是找到最右边位的位置 然后离开该位 我编写这段代码是为了这样做 int POS int n int p 0 while n if n 2 0 p else break n n 2 return p i
  • 在 C 语言中替换宏内的宏

    我正在尝试使代码部分可重用 我下面的评论片段没有达到我想要的效果 define NAME ABC define LOG SIZE NAME LEN 我想LOG SIZE决心ABC LEN 我尝试过使用 但没能让它发挥作用 LOG SIZE在
  • MSChart 控件中的自定义 X/Y 网格线

    我有一个带有简单 2D 折线图的 C Windows 窗体 我想向其中添加自定义 X 或 Y 轴标记 并绘制自定义网格线 例如 以突出显示的颜色 虚线 我查看了 customLabels 属性 但这似乎覆盖了我仍然想显示的默认网格 这是为了
  • 选择 asp.net CheckBoxList 中的所有项目

    ASP NET 和 C 我想要一个带有 全选 项目的复选框列表 当这个特定项目是 已选择 所有其他都将被选择 也 当选择被删除时 这个项目 也将来自所有人 其他物品 选中 取消选中 任何其他项目只会有一个 对特定项目的影响 无论选择状态如何
  • C++ 模板可以提供 N 个给定类的公共父类吗?

    我正在寻找一个 C 模板 它可以找到一组给定类的共同父级 例如 class Animal class Mammal public Animal class Fish public Animal class Cat public Mammal
  • 如何测试某些代码在 C++ 中无法编译? [复制]

    这个问题在这里已经有答案了 可能的重复 单元测试编译时错误 https stackoverflow com questions 605915 unit test compile time error 我想知道是否可以编写一种单元测试来验证给
  • 用数组或向量实现多维数组

    我想使用单个数组或向量实现多维数组 可以像通常的多维数组一样访问它 例如 a 1 2 3 我陷入困境的是如何实施 操作员 如果数组的维数为 1 则 a 1 应该返回位于索引 1 处的元素 但是如果维数大于一怎么办 对于嵌套向量 例如 3 维
  • 不使用放置 new 返回的指针时的 C++ 严格别名

    这可能会导致未定义的行为吗 uint8 t storage 4 We assume storage is properly aligned here int32 t intPtr new void storage int32 t 4 I k
  • 时间:2019-03-17 标签:c#TimerStopConfusion

    我想通过单击按钮时更改文本颜色来将文本框文本设置为 闪烁 我可以让文本按照我想要的方式闪烁 但我希望它在闪烁几次后停止 我不知道如何在计时器触发几次后让它停止 这是我的代码 public Form1 InitializeComponent
  • 初始化列表在 VC10 中不起作用

    我在 VC 2010 中编写了这个程序 class class1 public class1 initializer list
  • 对多个对象使用事件处理程序

    我有 20 件物品List
  • MSVC编译器下使用最大成员初始化联合

    我正在尝试初始化一个LARGE INTEGER在 C 库中为 0 确切地说是 C 03 以前 初始化是 static LARGE INTEGER freq 0 在 MinGW 下它产生了一个警告 缺少成员 LARGE INTEGER Hig
  • Unity,c++ 本机插件字节数组不匹配

    在我的 C 本机插件中 我有一个调用 vector
  • IDisposable 的显式实现

    虽然有很多关于IDisposable在 SO 上找到 我还没有找到答案 我通常遵循这样的做法 当我的一个班级拥有一个IDisposable对象然后它也实现IDisposable并打电话Dispose在拥有的对象上 然而最近我遇到了一个类 它

随机推荐

  • 一些使用 PDO 的 ORM?

    我正在寻找一个好的 ORM 即 Active Record 它使用 php 扩展 PDO 作为基础 有什么建议吗 Doctrine or Propel
  • 带有滚动区域的嵌套弹性盒

    我正在尝试在最新的 Chrome Firefox 和 IE11 中实现这种布局 我可以通过以下方式让它工作 html box sizing border box before after box sizing inherit html bo
  • Rails 控制器中创建方法的 SQL 注入预防

    如comment controller rb中所示 def create comment Comment new params comment comment save end 我假设这是 SQL 注入不安全的 但正确的做法是什么 网上的所
  • 重写 Django ModelForm 中的 save 方法

    我无法覆盖ModelForm保存方法 这是我收到的错误 Exception Type TypeError Exception Value save got an unexpected keyword argument commit 我的目的
  • 转换 osmnx 投影地图的经纬度坐标

    我想从 osmnx 获取距离经纬度对最近的节点 下载 osmnx 图形对象后 我想对其进行投影 以便我可以按照文档中的说明从道路网络中删除死胡同 我知道我投影了图表以及需要投影的纬度 经度值 但我实际上不明白以哪种方式 例如 我在我的项目中
  • 在不填充缺失时间的情况下重新采样 Pandas 数据帧

    对数据帧进行重新采样可以使数据帧达到更高或更低的时间分辨率 大多数情况下 这用于降低分辨率 例如 将 1 分钟数据重新采样为每月值 当数据集稀疏时 例如 2020 年 2 月没有收集任何数据 2020 年 2 月的行将填充重采样数据帧的 N
  • 多个
    标签的语义含义

    使用时 dl lists将键与值关联起来 这两个样本之间是否存在语义差异 哪一个提供更好的语义 多个做什么 dd 标签在这种情况下意味着什么 Sample 1 多种的 dd items dl dt Authors dt dd John Le
  • 阻止直接访问php页面,仅在重定向时访问

    我想让我的 php 页面只能从另一个页面重定向访问 并阻止我的用户直接访问它 我的意思是 假设我有一个名为 主 php 还有另一个我想阻止直接访问的 PHP 文件 名为 noaccess php 我想让 noaccess php 仅当我从
  • 在 Android 后台服务中静默 Google 登录

    我正在我的 Android 应用程序中运行后台服务 我使用从登录活动获取的 IdToken 在后端服务器上进行身份验证 该服务正在运行START STICKY模式 因此即使应用程序关闭 该服务也会在后台继续运行以获取来自后端服务器的任何通知
  • 如何正确混合Bootstrap和BEM?

    我正在考虑慢慢重构一个相当大的项目 该项目基于 Angular Bootstrap 构建 只有 16 000 多行 CSS 耶 我一直在越来越多地研究 BEM 并相信这将是一个很好的方法 我们也很有可能转向 React 我对此还不太了解 但
  • 无法在 1.1 版本中使用 1.2 标头编译 OpenCL 应用程序

    我正在使用 Khronos Group 编写一个小型 hello world OpenCL 程序cl hpp适用于 OpenCL 1 2 和 nVidia 的 openCL 库 我的驱动程序和 ICD 支持 OpenCL 1 1 由于 nV
  • 如何使通配符在 SQL Server 报告服务中的 like 运算符中起作用?

    我使用 like 运算符添加了一个过滤表达式 我在值字段中输入什么 我的参数名为 test 我希望过滤器的功能就像 SQL 中的 test 一样 我希望它的行为像 test 这样我就可以传递 来获取查询的所有值 我通过添加带有类似运算符的过
  • Gulp 4 - Gulpfile.js 设置

    我发现有关 Gulp 4 的文档非常难找到 所以我想我可以在这里询问是否有人可以提供帮助 无论如何 我对 Gulp 还很陌生 并且一直使用 Gulp 3 没有任何问题 直到我尝试在我们用于开发的虚拟机上运行它 我的 gulp 文件非常简单
  • 如何将我的 iOS 故事板设置为像 Instagram Stream 一样弹跳?

    我正在构建一个具有社交内容流的应用程序 并试图了解 Instagram 如何在应用程序中进行流式传输的行为 因此 基本上 顶部标题会滚动到屏幕之外 但会在屏幕和内容之间弹跳 我可以使顶部标题滚动离开屏幕 并且可以使视图不反弹 但我想使用拉动
  • Java 中日期到整数的转换

    我有一个 int 变量 如下所示 如何将其转换为 Date 对象 反之亦然 int inputDate 20121220 将值转换为String并使用SimpleDateFormat将其解析为Date object int inputDat
  • 检查矩阵是否奇异的快速方法? (不可逆,det = 0)

    检查小方阵 最好的方法是计算条件号通过 SVD 并检查它是否大于 1 epsilon 其中 epsilon 是机器精度 如果您允许漏报 即矩阵有缺陷 但您的算法可能无法检测到它 您可以使用维基百科文章中的 max a ii min a ii
  • MySQL 与 Group By 的一对多连接仅返回一个观察结果

    我有一个评论表和一个标签表 对于每个评论 可以有多个标签 也可以没有 我想加入这两个 这样我就可以获得每个评论的标签列表 评论表 CommentID Title 1 animals 2 plants 标签表 TagID CommentID
  • CustomTableCellView 的 -layoutSubviews 实现需要调用 super , NSInternalInconsistencyException

    在 tableView xib 的自定义单元格中使用 autoLayout 时 我收到以下错误 在 iOS 6 模拟器中运行时CustomCells的 layoutSubviews的实现需要调用super Assertion failure
  • 2 个双数之间的随机数

    是否可以在 2 个双精度数之间生成一个随机数 Example public double GetRandomeNumber double minimum double maximum return Random NextDouble min
  • 使用 SIMD 内在函数时这些额外的反汇编指令是什么?

    我正在测试使用 SIMD 指令与 RyuJIT 可以获得什么样的加速 并且我看到了一些我不期望的反汇编指令 我的代码基于这篇博文来自 RyuJIT 团队的 Kevin Frei 以及相关帖子here 这是函数 static void Add