(如何)使用 LLVM 机器代码分析器预测代码片段的运行时间?

2023-11-22

我使用 llvm-mca 来计算总周期一段代码,认为他们会预测它的运行时间。然而,动态测量运行时间几乎没有相关性。所以:为什么 llvm-mca 计算的总周期不能准确预测运行时间?我可以使用 llvm-mca 以更好的方式预测运行时间吗?


Details:

我想知道以下代码对于不同类型的运行时begin (and end) 迭代器,对于startValue being 0.0 or 0ULL:

std::accumulate(begin, end, starValue)

为了预测运行时间,我使用了编译器资源管理器(https://godbolt.org/z/5HDzSF)及其 LLVM 机器代码分析器 (llvm-mca) 插件,因为 llvm-mca 是“一种性能分析工具,它使用 LLVM 中可用的信息(例如调度模型)来静态测量性能”。我使用了以下代码:

using vec_t = std::vector<double>;

vec_t generateRandomVector(vec_t::size_type size)
{
    std::random_device rnd_device;
    std::mt19937 mersenne_engine {rnd_device()};
    std::uniform_real_distribution dist{0.0,1.1};
    auto gen = [&dist, &mersenne_engine](){
        return dist(mersenne_engine);
    };
    vec_t result(size);
    std::generate(result.begin(), result.end(), gen);
    return result;
}

double start()
{
    vec_t vec = generateRandomVector(30000000);
    vec_t::iterator vectorBegin = vec.begin();
    vec_t::iterator vectorEnd = vec.end();
    __asm volatile("# LLVM-MCA-BEGIN stopwatchedAccumulate");
    double result = std::accumulate(vectorBegin, vectorEnd, 0.0);
    __asm volatile("# LLVM-MCA-END");    
    return result;
}

但是,我发现 llvm-mca 的总周期计算机与运行相应的 std::accumulate 的挂钟时间之间没有相关性。例如,在上面的代码中,总周期为 2806,运行时间为 14ms。当我切换到 startValue 时0ULL,总周期为 2357,但运行时间为 117ms。


TL:DR: LLVM-MCA 分析了这些注释之间的整个代码块,就好像它是body一个循环,并向您显示所有这些指令 100 次迭代的循环计数。

但除了实际(微小)循环之外,大多数指令都是循环设置以及循环后的 SIMD 水平求和,实际上只运行一次。 (这就是为什么周期数是数千,而不是 400 = 100 倍的 4 周期延迟vaddpd在 Skylake 上0.0版本带有double累加器。)

如果您取消选中 Godbolt 编译器资源管理器上的“//”框,或者修改 asm 语句以添加 nop ,例如"nop # LLVM-MCA-END",您将能够在 asm 窗口中找到这些行,并查看 LLVM-MCA 正在查看的内容,因为它是“循环”。


LLVM MCA 模拟指定的汇编指令序列并计算估计执行所需的周期数每次迭代在指定的目标架构上。 LLVM MCA 进行了许多简化,例如(我突然想到):(1)它假设所有条件分支都失败,(2)它假设所有内存访问都是写回内存类型并且全部命中L1 缓存,(3) 假设前端工作最佳,(4)call被调用的过程中没有遵循指令,它们就会失败。还有其他假设,我目前不记得了。

本质上,LLVM MCA(如英特尔 IACA)仅适用于后端计算绑定的简单循环。在 IACA 中,虽然支持大多数指令,但仍有少数指令没有详细建模。例如,假设预取指令仅消耗微架构资源,但延迟基本上为零,并且对存储器层次结构的状态没有影响。然而,在我看来,马华完全忽视了这样的指示。无论如何,这与你的问题不是特别相关。

现在回到你的代码。在您提供的编译器资源管理器链接中,您没有将任何选项传递给 LLVM MCA。因此,默认的目标架构生效,即该工具运行的任何架构。这恰好是SKX。您提到的总周期数是针对 SKX 的,但不清楚您是否在 SKX 上运行代码。您应该使用-mcpu指定架构的选项。这独立于-march你转到了海湾合作委员会。另请注意,将核心周期与毫秒进行比较是没有意义的。您可以使用RDTSC用于测量以核心周期为单位的执行时间的指令。

请注意编译器如何内联对std::accumulate。显然,这段代码从装配线 405 开始,也是该指令的最后一条指令。std::accumulate位于第444行,共38条指令。 LLVM MCA 估计与实际性能不符的原因现在已经很清楚了。该工具假设所有这些指令都在循环中执行大量迭代。显然事实并非如此。 420-424之间只有一个循环:

.L75:
        vaddpd  ymm0, ymm0, YMMWORD PTR [rax]
        add     rax, 32
        cmp     rax, rcx
        jne     .L75

仅应将此代码输入到 MCA。在源代码级别,确实没有办法告诉 MCA 只分析这段代码。你必须手动内联std::accumulate并放置LLVM-MCA-BEGIN and LLVM-MCA-END在其内部某处进行标记。

经过时0ULL代替0.0 to std::accumulate,LLVM MCA 的输入将从汇编指令 402 开始,到 441 结束。请注意,MCA 不支持任何指令(例如vcvtsi2sdq)将在分析中完全省略。代码中实际处于循环中的部分是:

.L78:
        vxorpd  xmm0, xmm0, xmm0
        vcvtsi2sdq      xmm0, xmm0, rax
        test    rax, rax
        jns     .L75
        mov     rcx, rax
        and     eax, 1
        vxorpd  xmm0, xmm0, xmm0
        shr     rcx
        or      rcx, rax
        vcvtsi2sdq      xmm0, xmm0, rcx
        vaddsd  xmm0, xmm0, xmm0
.L75:
        vaddsd  xmm0, xmm0, QWORD PTR [rdx]
        vcomisd xmm0, xmm1
        vcvttsd2si      rax, xmm0
        jb      .L77
        vsubsd  xmm0, xmm0, xmm1
        vcvttsd2si      rax, xmm0
        xor     rax, rdi
.L77:
        add     rdx, 8
        cmp     rsi, rdx
        jne     .L78

注意这里有一个条件跳转,jns,在目标地址位于块中某处的代码中。 MCA 只会假设跳跃会失败。如果实际运行代码时情况并非如此,MCA 将不必要地增加 7 条指令的开销。还有一次跳跃,jb,但我认为这对于大向量来说并不重要,并且大多数时候都会失败。最后一跳,jne,也是最后一条指令,因此 MCA 会假设下一条指令又是最上面的指令。对于足够多的迭代次数,这个假设是完全正确的。

总的来说,很明显第一个代码比第二个代码小得多,因此它可能要快得多。您的测量确实证实了这一点。您实际上也不需要使用微架构分析工具来理解原因。第二个代码只是做了更多的计算。所以你可以很快得出结论:通过0.0在所有架构上的性能和代码大小方面都更好。

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

(如何)使用 LLVM 机器代码分析器预测代码片段的运行时间? 的相关文章

  • 单元测试验证失败

    我正在运行我的单元测试PostMyModel路线 然而 在PostMyModel 我用的是线Validate
  • 在 OnModelCreating 期间设置列名称

    Issue 我目前正在尝试通过设置的属性为我的表及其列添加前缀 我正在使用实体框架核心 我已经正确地为表名添加了前缀 但我似乎无法弄清楚列的前缀 我有一种感觉 我需要使用反射 我已经留下了我的 可能很糟糕的 反思尝试 有人有办法在实体中设置
  • C++ 长 switch 语句还是用地图查找?

    在我的 C 应用程序中 我有一些值充当代表其他值的代码 为了翻译代码 我一直在争论使用 switch 语句还是 stl 映射 开关看起来像这样 int code int value switch code case 1 value 10 b
  • linq 中使用字符串数组 c# 的 'orderby'

    假设我有一个这样的方法定义 public CustomerOrderData GetCustomerOrderData string CustomerIDs var query from a in db Customer join b in
  • CSharpRepl emacs 集成?

    我碰巧知道莫诺CSharpRepl http www mono project com CsharpRepl 是否有 emacs csharp 模式使用它在一个窗口中运行 REPL 并像 python 模式一样在另一个窗口中编译 运行 C
  • 运行需要 MySql.Data 的内置 .NET 应用程序

    我在运行我编写的内置 NET 应用程序时遇到问题 我的应用程序使用最新的 MySql 连接器 该连接器安装在我的系统上 当我尝试将其添加为引用时 该连接器显示为 NET 4 Framwork 组件 当我在环境中以调试模式运行应用程序时 一切
  • Gwan C#,如何获取HTTP标头?

    我需要它来重写 url 以了解我正在处理哪个友好的 url 用于用户代理和其他东西 EDIT public class Gwan MethodImplAttribute MethodImplOptions InternalCall exte
  • 如何制作可启动程序?

    所以 这个问题可能看起来很奇怪 但假设我编译了 int main void int x 3 int y 4 int z x y 是否可以让CPU这样运行 如何 例如 这允许我写入监视器吗 如果我没记错的话 内存中有些地方可以写入要显示的内容
  • 在 omp 并行 for 循环中使用 unique_ptr 会导致 SEG.FAULT

    采取以下代码 include
  • 将表(行)与 OpenXML SDK 2.5 保持在一起

    我想在 Word 文档中生成多个表 每行 2 行 但我想将这两行保留在一起 如果可能的话 new KeepNext 第一行不起作用 new KeepNext 第一行的最后一段不起作用 new CantSplit 放在桌子上不起作用 在所有情
  • 访问 ascx 文件中的母版页控件

    我有一个母版页文件 其中包含 2 个面板控件中的 2 个菜单 我还使用控件来检查用户是否登录并获取用户类型 根据我想要显示 隐藏面板的类型 控件本身不在母版页中引用 而是通过 CMS 系统动态引用 我想在用户控件中使用findcontrol
  • 使用查询表达式对 List 进行排序

    我在使用 Linq 订购这样的结构时遇到问题 public class Person public int ID get set public List
  • MFC:如何设置CEdit框的焦点?

    我正在开发我的第一个简单的 MFC 项目 但我正在努力解决一个问题 想要设置所有的焦点CEdit其中一个对话框中的框 我的想法是 当打开对话框时 焦点位于第一个编辑框上 然后使用 选项卡 在它们之间交换 我看到了方法SetFocus 但我无
  • 将接口转换为其具体实现对象,反之亦然?

    在 C 中 当我有一个接口和几个具体实现时 我可以将接口强制转换为具体类型 还是将具体类型强制转换为接口 这种情况下的规则是什么 Java 和 C 中都允许这两个方向 向下转型需要显式转型 如果对象类型不正确 可能会抛出异常 然而 向上转换
  • 根据对象变量搜索对象列表

    我有一个对象列表 这些对象具有三个变量 ID 名称和值 这个列表中可能有很多对象 我需要根据ID或Name找到一个对象 并更改值 例子 class objec public string Name public int UID public
  • 使用 GCC 生成可读的程序集?

    我想知道如何使用GCC http en wikipedia org wiki GNU Compiler Collection在我的 C 源文件中转储机器代码的助记符版本 这样我就可以看到我的代码被编译成什么 你可以使用 Java 来做到这一
  • 选择查询不适用于使用Parameters.AddWithValue 的参数

    C 中的以下查询不起作用 但我看不出问题所在 string Getquery select from user tbl where emp id emp id and birthdate birthdate cmdR Parameters
  • 在 C#.NET 中安全删除文件

    在我正在做的一个项目中 我想为用户提供 安全 删除文件的选项 例如 用随机位或 0 覆盖它 在 C NET 中是否有一种简单的方法可以做到这一点 效果如何 你可以调用系统内部删除 http technet microsoft com en
  • LINQ 中的“from..where”或“FirstOrDefault”

    传统上 当我尝试从数据库中获取用户的数据时 我使用了以下方法 在某种程度上 DbUsers curUser context DbUsers FirstOrDefault x gt x u LoginName id string name c
  • 使用 numpy 加速 for 循环

    下一个 for 循环如何使用 numpy 获得加速 我想这里可以使用一些奇特的索引技巧 但我不知道是哪一个 这里可以使用 einsum 吗 a 0 for i in range len b a numpy mean C d e f b i

随机推荐

  • 加载视频 mp4 webpack 加载器

    如何使用 webpcak 4 加载 mp4 视频格式 我尝试如下 test mp4 use file loader loader file loader name videos name ext 并像这样导入 import pressBut
  • Jquery 的 Ajax 自动完成:如何发送动态参数

    我在用Ajax Autocomplete for Jquery http www devbridge com projects autocomplete jquery 在我的一个应用程序中 搜索表单看起来像这样
  • 如何查看 AngularDart 集合的元素?

    我有一个模型 class WordList List
  • AH=2 的 BIOS INT 13H 每次只能读取 72 个扇区。为什么?

    我正在使用 Bochs 2 4 5 编写引导扇区代码 我使用 INT 13H 从软盘读取扇区 但我发现如果读取的扇区数 gt 72 INT13就会失败 返回码为AH 1 下面是代码 这是INT13 返回码为AH 1 为什么INT 13H不能
  • NoMethodError:推送到 Heroku 时,nil:NilClass 未定义方法“[]”

    这里是 Rails 菜鸟 我在推送到 Heroku 时遇到了问题 NoMethodError nil NilClass 的未定义方法 我什至不确定应该从哪里开始解决这个问题 remote gt Preparing app for Rails
  • Twitter Bootstrap 在表格单元格上使用collapse.js [即将完成]

    我正在开发一个列出交易 贷方和借方 的帐户页面 我希望用户能够单击表行 它会展开以显示更多信息 我正在使用 Twitter bootstrap 并查看了文档 这是我得到的结果 table class table table striped
  • 使用 cURL 通过 Powershell 2.0 发出 POST 请求

    Scenario 除此之外 Powershell 2 0 没有有用的 cmdlet Invoke RestMethod 我无法升级到版本 3 而且我发现的大多数示例都使用版本 3 我已经发现本文 然而 对于我的简单场景来说 这似乎太复杂了
  • 设置以编程方式添加的视图的样式

    在我的代码中 我以编程方式将单选按钮 复选框等输入元素添加到我的布局中 问题是 当您通过 xml 添加 radioButton 时 这些元素的样式不是您将获得的默认样式 它看起来真的很白 在白色应用程序背景上几乎是透明的 有点像透明的 另外
  • Paint() 和 PaintComponent() 之间的区别?

    我已经尝试过这方面的教程 但我仍然不太明白 基本上我的问题是哪种方法更好 为什么 我应该使用paint or paintComponent 请尽量让答案简单一些 谢谢 引用自文档paint method 该方法实际上将绘画工作委托给三个受保
  • 可以从 Google 地图 API 中提取行程预计到达时间吗?

    是否可以从两个地址点之间的谷歌地图 API 获取行程预计到达时间 以分钟为单位 和交通数据 有谁知道ETA值是否反映了交通状况 谷歌有一个距离矩阵API返回两个 或多个 点之间的距离和行进时间 可以指定为 lat lng 或地址 我不认为它
  • Spring Boot Tomcat 配置,从容器迁移到嵌入式

    我正在将用于在 Tomcat 容器中运行的 Spring Boot 应用程序迁移到运行嵌入式 Tomcat 的 Spring Boot 应用程序 我的旧 Tomcat 配置在 server xml 中有以下配置
  • 生产中的 CouchDB

    我一直在一些原型应用程序上使用 CouchDB 它非常出色 非常易于使用并且速度非常快 我想知道是否有人在生产中使用过它 并对它的可靠性 操作管理的性能适用性等有什么看法 我正在考虑使用它来支持服务层并利用其复制功能 任何评论 经验都将受到
  • 将焦点设置在 元素上

    我正在使用 Angular 5 开发前端应用程序 我需要隐藏一个搜索框 但单击按钮后 应该显示搜索框并聚焦 我已经尝试了在 StackOverflow 上找到的一些带有指令的方法 但无法成功 这是示例代码 Component selecto
  • Bootstrap 轮播 - YouTube 视频播放时暂停

    我的 Bootstrap 轮播中有一些嵌入的 YouTube 视频 默认情况下 轮播会自动前进 但我想在视频播放时暂停 有没有什么技巧可以检测视频何时播放 如果可能的话 我希望不使用 YouTube API 来完成此操作 每个轮播都有任意数
  • 如何从字符串中删除所有字符

    如何使用 JavaScript 正则表达式从字符串中删除所有非字母字符 您可以使用replace method Hey The 123 sure is fun replace A Za z g gt gt gt HeyThesureisfu
  • 使用 django-axes 登录 Django

    我用 django 创建了一个网站 用户应该能够登录 登录视图如下所示 from django contrib auth import authenticate login from django contrib auth models i
  • 如何让JFrame透明?

    如何让JFrame透明 我想让我的 JFrame 透明 当我的 JFrame 位于背景之上时 用户应该看到背景 我找到了另一个解决方案 将框架的背景颜色设置为 Set the frame background color to a tran
  • scikit-learn 中带有 BaseEstimator 的 GradientBoostingClassifier?

    我尝试在 scikit learn 中使用 GradientBoostingClassifier 它使用默认参数可以正常工作 但是 当我尝试用不同的分类器替换 BaseEstimator 时 它不起作用并给出以下错误 return y np
  • Slick/Scala:什么是 Rep[Bind] 以及如何将其转换为值?

    我正在尝试找出 Slick Scala 函数关系模型 我已经开始在 Slick 3 0 0 中构建原型 但是当然 大多数文档要么已过时 要么不完整 我已经成功地达到了可以创建模式并从数据库返回对象的程度 问题是 我返回的是 Rep Bind
  • (如何)使用 LLVM 机器代码分析器预测代码片段的运行时间?

    我使用 llvm mca 来计算总周期一段代码 认为他们会预测它的运行时间 然而 动态测量运行时间几乎没有相关性 所以 为什么 llvm mca 计算的总周期不能准确预测运行时间 我可以使用 llvm mca 以更好的方式预测运行时间吗 D