涉及 sin() 的两个非常相似的函数表现出截然不同的性能 - 为什么?

2023-12-31

考虑以下两个程序,它们以两种不同的方式执行相同的计算:

// v1.c
#include <stdio.h>
#include <math.h>
int main(void) {
   int i, j;
   int nbr_values = 8192;
   int n_iter = 100000;
   float x;
   for (j = 0; j < nbr_values; j++) {
      x = 1;
      for (i = 0; i < n_iter; i++)
         x = sin(x);
   }
   printf("%f\n", x);
   return 0;
}

and

// v2.c
#include <stdio.h>
#include <math.h>
int main(void) {
   int i, j;
   int nbr_values = 8192;
   int n_iter = 100000;
   float x[nbr_values];
   for (i = 0; i < nbr_values; ++i) {
      x[i] = 1;
   }
   for (i = 0; i < n_iter; i++) {
      for (j = 0; j < nbr_values; ++j) {
         x[j] = sin(x[j]);
      }
   }
   printf("%f\n", x[0]);
   return 0;
}

当我使用 gcc 4.7.2 编译它们时-O3 -ffast-math在 Sandy Bridge 盒子上运行时,第二个程序的速度是第一个程序的两倍。

这是为什么?

一个怀疑是连续迭代之间的数据依赖性i循环进入v1。但是,我不太明白完整的解释可能是什么。

(问题的灵感来自为什么我的 python/numpy 示例比纯 C 实现更快? https://stackoverflow.com/questions/14466950/why-is-my-python-numpy-example-faster-than-pure-c-implementation)

EDIT:

这是生成的程序集v1:

        movl    $8192, %ebp
        pushq   %rbx
LCFI1:
        subq    $8, %rsp
LCFI2:
        .align 4
L2:
        movl    $100000, %ebx
        movss   LC0(%rip), %xmm0
        jmp     L5
        .align 4
L3:
        call    _sinf
L5:
        subl    $1, %ebx
        jne     L3
        subl    $1, %ebp
        .p2align 4,,2
        jne     L2

and for v2:

        movl    $100000, %r14d
        .align 4
L8:
        xorl    %ebx, %ebx
        .align 4
L9:
        movss   (%r12,%rbx), %xmm0
        call    _sinf
        movss   %xmm0, (%r12,%rbx)
        addq    $4, %rbx
        cmpq    $32768, %rbx
        jne     L9
        subl    $1, %r14d
        jne     L8

完全忽略循环结构,只考虑调用顺序sin. v1执行以下操作:

x <-- sin(x)
x <-- sin(x)
x <-- sin(x)
...

也就是说,每次计算sin( )在上一个调用的结果可用之前无法开始;它必须等待整个先前的计算。这意味着对于 N 次调用sin,总共需要的时间是单个延迟的819200000倍sin评估。

In v2,相比之下,您执行以下操作:

x[0] <-- sin(x[0])
x[1] <-- sin(x[1])
x[2] <-- sin(x[2])
...

请注意,每次调用sin不依赖于之前的调用。实际上,调用sin都是独立的,只要必要的寄存器和 ALU 资源可用,处理器就可以开始处理每个计算(无需等待先前的计算完成)。因此,所需时间是吞吐量sin 函数的值,而不是延迟的值,等等v2可以在更短的时间内完成。


我还应该指出 DeadMG 是对的v1 and v2形式上是等价的,在完美的世界中,编译器会将它们优化为 100000 的单个链sin评估(或简单地在编译时评估结果)。可悲的是,我们生活在一个不完美的世界。

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

涉及 sin() 的两个非常相似的函数表现出截然不同的性能 - 为什么? 的相关文章

随机推荐

  • 将 SQL 数据从一个表移动到另一个表

    我想知道是否可以将与某个查询匹配的所有数据行从一个表移动到另一个表 例如 我需要将所有表行从 Table1 移动到 Table2 其中用户名 X 和密码 X 以便它们不再出现在 Table1 中 我正在使用 SQL Server 2008
  • NodeJS 套接字 IO 停止随机发出?

    我正在运行 Node 0 6 16 并且所有模块至少根据 npm win7 x64 都是最新的 我注意到 即使没有发生断开连接 但由于某种原因 过了一会儿 我无法判断 也许1小时后 浏览器没有收到任何数据 它在 FF 上似乎比在 Chrom
  • ASP.NET vNext 可以使用非 vNext 引用吗?

    所以我在 VS 14 CTP 中有一个 ASP NET vNext 项目 我的目标是 NET Framework 4 5 1 我添加了对 NuGet 包的引用 该包没有特定于 vNext 的构建 Visual Studio 现在在编辑器 I
  • 视频无法在 iPad/iPhone 上播放

    我正在建立一个网站 daratogaincontrol com 在该网站上 我使用 videolightbox 来播放视频 这些视频无法在 iPad 或 iPhone 上播放 该网站在台式机 Mac 和 PC 上运行良好 videoligh
  • 存储 1 到 1000 素数的链表

    正如您将在以下程序的注释中看到的那样 我应该创建一个列表来存储从 1 到 1000 的所有素数并释放节点 其中只有两个功能是我的工作 然而 我很长时间都没有弄清楚为什么这个程序不能编译 你们看到错误了吗 这是已经交的作业 仅供我个人参考 i
  • 防止创建配置文件

    我正在尝试构建一个包 其中包含一些文件 etc那些不是配置 它们包含在conffiles即使我创建一个空的也自动package conffiles in the debian目录 我怎样才能停下来dh installdeb这样做 我不确定我
  • 在 Eclipse 中设置自定义语法突出显示的快速方法

    我知道我不是第一个需要这个的人 我正在开发一个内部创建的代码库 我想在 Eclipse 中对其应用突出显示 在 Notepad 中 我可以为我正在查看的文件设置语言 有什么办法可以为 Eclipse 做到这一点吗 我正在编写的代码将使用与
  • 如何在 Python 中编写一个函数将 csv 的每一行翻译成另一种语言?

    如何在 Python 中编写一个函数 将 csv 文件的每一行翻译为另一种语言 并使用 pandas 将翻译作为另一列添加到同一 csv 中 我的输入文件如下所示 我希望我的输出是这样的 我是这样开始的 from googletrans i
  • ActionController::UrlGenerationError,没有路由匹配

    我已经阅读了我能找到的所有类似问题 但仍然无法找出我的问题 routes rb Rails application routes draw do resources lists only index show create update d
  • 将装饰器列表应用于可调用对象?

    给定一系列装饰器方法 如何将它们应用于可调用对象 例如 因为 foo bar def baz pass 是相同的 def baz pass baz foo bar baz 人们会假设有一个装饰器列表 foo bar 它们可以应用于baz动态
  • ms-access:数据库引擎找不到输入表或查询

    这是查询 SELECT FROM SELECT Occurrence Number Occurrence Date 1 0 Preanalytical Before Testing Cup Type NULL as 2 0 Analytic
  • 找不到“id”=sign_out 的用户

    我正在 Rails 中使用设备 但现在无法注销我的用户 当我使用 users log out 页面时 出现以下错误 ActiveRecord RecordNotFound in UsersController show Couldn t f
  • 为ggmap创建base_layer无法识别data.frame

    我正在尝试使用 ggmap 在地图上绘制位置 因为我想使用分面 所以我必须提供base layer论证ggmap 我也试图将其包装在一个函数中 我有定义地图边界框的变量 long range lt c 71 5 67 5 lat range
  • cakephp 2.0 smtp 电子邮件

    我正在尝试使用 CakePhp 2 0 发送电子邮件 在我的控制器中我使用这个代码 我知道它很好 我从烹饪书 http book cakephp org 2 0 en core utility libraries email html Ap
  • Python 中从右到左的字符串替换?

    我想在 Python 中进行字符串替换 但只执行从右到左的第一个实例 在理想的世界中我会 myStr mississippi print myStr rreplace iss XXX 1 gt missXXXippi 鉴于此 最好的方法是什
  • Sublime 就像 HTML5 中的多个光标

    您知道如何在浏览器中使用 Sublime 或 Cloud 9 之类的多光标功能吗 我想要多个光标textarea 可能在多个文本区域中 应该可以使用 HTML5 但在网络上没有找到任何内容 谢谢你 正如巴洛普所说王牌编辑有多个光标 如果你想
  • VB6 - Foxpro 2.6 XP 上没有 isam 错误

    老板给了我一些相当古老的遗留代码 全部用 VB6 完成 安装 Visual Studio 6 和其他一些东西后 我终于能够打开该项目并实际编译 运行它 我的新问题来自这行代码 Set db DBEngine Workspaces 0 Ope
  • 为什么在 Ruby 中捕获命名组会导致“未定义的局部变量或方法”错误?

    我在 Ruby 2 0 中的正则表达式中的命名捕获方面遇到问题 我有一个字符串变量和一个内插正则表达式 str hello world re w
  • 使用VBA检查下面的单元格是否为空

    如何在 Excel 中使用 VBA 检查下面的单元格是否为空 我想对特定范围内的所有值求和 但前提是下面的单元格不为空 通过 VBA 或任何其他方式可以实现这一点吗 Example 4 2 3 2 1 2 3 1 总和为 4 3 2 9 尝
  • 涉及 sin() 的两个非常相似的函数表现出截然不同的性能 - 为什么?

    考虑以下两个程序 它们以两种不同的方式执行相同的计算 v1 c include