为什么矢量化通常比循环更快?

2024-04-17

为什么在执行操作的硬件的最低级别和所涉及的一般底层操作(即:运行代码时所有编程语言的实际实现通用的事情),矢量化通常比循环快得多?

计算机在循环时会做什么而在使用矢量化时不会做什么(我指的是计算机执行的实际计算,而不是程序员编写的计算),或者它有什么不同的做法?

我一直无法说服自己为什么差异如此之大。我可能会相信矢量化代码在某处减少了一些循环开销,但计算机仍然必须执行相同数量的操作,不是吗?例如,如果我们将一个大小为 N 的向量乘以一个标量,那么我们将执行 N 次乘法,不是吗?


矢量化(通常使用该术语)是指 SIMD(单指令、多数据)操作。

从本质上讲,这意味着一条指令对多个操作数并行执行相同的操作。例如,要将大小为 N 的向量乘以标量,我们将 M 称为它可以同时操作的大小的操作数的数量。如果是这样,那么它需要执行的指令数量大约为 N/M,其中(使用纯标量操作)它必须执行 N 个操作。

例如,Intel当前的AVX 2指令集使用256位寄存器。它们可用于保存(并操作)一组 4 个 64 位操作数,或 8 个 32 位操作数。

因此,假设您正在处理 32 位单精度实数,这意味着一条指令可以一次执行 8 次运算(在您的情况下为乘法),因此(至少在理论上)您可以使用以下命令完成 N 次乘法只有N/8乘法指令。至少,从理论上讲,这应该允许操作完成速度大约是一次执行一条指令所允许的速度的 8 倍。

当然,确切的好处取决于每条指令支持多少个操作数。 Intel 的第一次尝试仅支持 64 位寄存器,因此要同时操作 8 个项目,这些项目每个只能是 8 位。他们目前支持 256 位寄存器,并且已经宣布支持 512 位(他们甚至可能在一些高端处理器中提供这种支持,但至少在普通消费处理器中还没有提供)。温和地说,充分利用此功能也并非易事。安排指令以使您实际上拥有 N 个可用操作数并在正确的时间将其放置在正确的位置并不一定是一项简单的任务(根本)。

从长远来看,(现在已经很古老的)Cray 1 正是通过这种方式获得了很大的速度。它的向量单元在 64 个寄存器组上运行,每个寄存器为 64 位,因此每个时钟周期可以执行 64 次双精度运算。在最佳矢量化代码上,它比您仅根据其(低得多)时钟速度所预期的速度更接近当前 CPU 的速度。充分利用这一点并不总是那么容易(而且仍然不是)。

Keep in mind, however, that vectorization is not the only way in which a CPU can carry out operations in parallel. There's also the possibility of instruction-level parallelism, which allows a single CPU (or the single core of a CPU) to execute more than one instruction at a time. Most modern CPUs include hardware to (theoretically) execute up to around 4 instructions per clock cycle1 if the instructions are a mix of loads, stores, and ALU. They can fairly routinely execute close to 2 instructions per clock on average, or more in well-tuned loops when memory isn't a bottleneck.

当然,还有多线程——在(至少逻辑上)单独的处理器/内核上运行多个指令流。

因此,现代 CPU 可能有 4 个内核,每个内核每个时钟可以执行 2 个向量乘法,并且每个指令可以对 8 个操作数进行操作。因此,至少在理论上,每个时钟可以执行 4 * 2 * 8 = 64 次操作。

有些指令具有更好或更差的吞吐量。例如,FP 增加的吞吐量低于 FMA,或者在 Skylake 之前在 Intel 上倍增(每个时钟 1 个向量,而不是 2 个向量)。但是像 AND 或 XOR 这样的布尔逻辑每个时钟吞吐量有 3 个向量;构建 AND/XOR/OR 执行单元并不需要很多晶体管,因此 CPU 会复制它们。使用高吞吐量指令时,总管道宽度(解码并发出到核心无序部分的前端)上的瓶颈很常见,而不是特定执行单元上的瓶颈。


  1. 但是,随着时间的推移,CPU 往往会拥有更多可用资源,因此这个数字会上升。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么矢量化通常比循环更快? 的相关文章

  • Mongodb聚合框架:$group是否使用索引?

    我正在尝试使用聚合框架 match and group阶段 做 group阶段使用索引数据 我正在使用最新的可用 mongodb 版本 2 5 4 group不使用索引数据 来自 mongoDBdocs http docs mongodb
  • 使用 JOIN 或 EXISTS 可以获得更好的性能吗?

    我有两个表格 机构 和 结果 我想查看机构是否有任何结果 这样我就可以排除没有结果的机构 使用 JOIN 或 EXISTS 可以获得更好的性能吗 谢谢你 Nimesh 根据语句 统计信息和数据库服务器 这可能没有什么区别 可能会生成相同的优
  • 反序列化 XML 文件而不将其全部加载到内存中 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 假设您的应用程序使用 XmlSerializer 序列化对象 当应用程序的另一部分 例如外部服务或另一个组件 处理该 XML 文件时 会返回一个
  • SQL Server 2005存储过程性能问题

    我遇到以下问题 当从我的应用程序调用存储过程时 时不时地 例如 1000 次调用中的 1 次 需要 10 30 秒才能完成 通常 存储过程的运行时间不到一秒 这是一个相当简单的过程 只需一个选择即可将几个表连接在一起 所有表名都设置有 NO
  • 如何从 Hudson CI API 获得更好的性能?

    我正在尝试为自己编写一个与 Hudson 构建服务器集成的小工具 我目前遇到的障碍是性能 我想做一件简单的事情 比如列出所有作业和上次成功构建的时间 hudson API 提供了此信息 但我要么必须查询所有内容depth 2或者单独查询每个
  • SQL 中的 JOIN 成本有多高?和/或,性能和标准化之间的权衡是什么?

    我发现了一个类似的线程 但它并没有真正抓住我想要问的本质 所以我创建了一个新线程 我知道规范化和性能之间存在权衡 我想知道划定这条线的最佳实践是什么 在我的特定情况下 我有一个消息传递系统 它具有三个不同的表 messages thread
  • 为什么 Python 对于一个简单的 for 循环来说这么慢?

    我们正在做一些kNN and SVDPython 中的实现 其他人选择了 Java 我们的执行时间非常不同 我使用 cProfile 来查看我在哪里犯了错误 但一切都很好fine http wiki python org moin Pyth
  • 使用 Numba 加速矢量距离计算

    以下是我为 3 D 环形几何中的距离 平方 计算编写的一些函数 用于该 3 D 空间中的粒子集合 import itertools import time import numpy as np import scipy import num
  • 与 SSE 比较 16 字节字符串

    我有 16 字节的 字符串 它们可能更短 但您可能会假设它们在末尾用零填充 但您可能不会假设它们是 16 字节对齐的 至少不总是 如何编写一个例程将它们与 SSE 内在函数进行比较 是否相等 我发现这个代码片段可能会有帮助 但我不确定它是否
  • 样式组件如何影响性能?

    使用样式组件是否比样式表更会降低 Web 应用程序的速度 如果我关心性能并且没有任何依赖于 props 的样式 我是否应该放弃样式组件并使用样式表 当您有很多小组件时 同时使用样式化组件渲染 性能开销可能会很有意义 绝对值得测试以删除小元素
  • 如何知道您的单元测试装置是否“尺寸合适”?

    您如何知道 测试夹具 的尺寸是否合适 我所说的 测试夹具 是指一个包含大量测试的类 我在测试装置中一直注意到的一件事是它们变得有点冗长 鉴于它们也可能不够详细 您如何了解单元测试的大小是否合适 我的假设是 至少在 Web 开发的背景下 您应
  • STL 容器速度与数组

    我刚刚开始从事一个科学项目 其中速度非常重要 HPC 我目前正在设计数据结构 该项目的核心是双值 3D 网格 以求解偏微分方程 由于这里的速度可能比代码的简单性更重要 我想知道 STL 与通常的 C 风格数组相比如何执行 就我而言 因为它是
  • 使用map.get()时使用java Map.containsKey()是多余的

    一段时间以来 我一直想知道在最佳实践中是否允许避免使用containsKey 方法上java util Map而是对结果进行空检查get 我的理由是 两次查找值似乎是多余的 首先是查找containsKey 然后再次为get 另一方面 大多
  • 空 while 循环有什么影响?

    我知道这可能是一个有点 愚蠢 的问题 但有时 我只想循环直到条件为假 但我不喜欢让循环保持为空 所以代替 Visible true while IsRunning Visible false 我通常prefer while IsRunnin
  • 嵌套辅助函数和性能

    嵌套辅助函数对于使代码更易于理解非常有用 谷歌甚至建议在他们的应用程序中使用嵌套函数时尚指南 https google styleguide googlecode com svn trunk javascriptguide xml Nest
  • 对于双核手机,availableProcessors() 返回 1

    我最近购买了一部 Moto Atrix 2 手机 当我尝试查看手机中的处理器规格时 Runtime getRuntime availableProcessors 返回 1 proc cpuinfo 也仅包含有关处理器 0 的信息 出于好奇
  • .NET 中 UniqueQueue 和 UniqueReplacementQueue 集合最有效的实现

    考虑到入队和出队操作的速度同样重要 NET 中 UniqueQueue 和 UniqueReplacementQueue 集合最有效 就速度而言 的实现是什么 UniqueQueue是一个不可能出现重复的队列 因此 如果我将一个元素推送到队
  • 在Python列表中交换元素的最快方法

    在Python中交换两个列表元素是否有比 L a L b L b L a 或者我必须求助于Cython http cython org or Weave http www scipy org Weave或类似的 看起来 Python 编译器
  • 比较运算符性能 <= 与 !=

    让我们首先声明代码可读性胜过微优化 我们应该将其留给编译器 这只是一个奇怪的案例 具体细节似乎与一般建议相比很有趣 因此 我在搞素数生成器函数 并提出了一种奇怪的行为 其中 人们建议效率最高 实际上效率最低 而 C private stat
  • 用于选择特定 div 中具有特定类的锚元素的 jQuery 选择器是什么

    我有一些这样的代码 我想选择每个 a 带有类的标签status在 div 中foo div a class status a div 你可以这样做 foo find status a

随机推荐

  • LinqToExcel:Excel 列中的不同值

    对于各位专家来说 这可能是一件非常简单的事情 但我对 C 4 和 INTEROP 并不熟悉 因此 我很困惑 这是我的问题 我有一个包含重复数据的 Excel 列 我想将其修剪为仅具有唯一值 数据如下所示 ColA ColB 10 Adam
  • 角度表单验证 ng-disabled 不起作用

    我正在尝试在我的博客文章表单中使用角度表单验证 更具体地说是禁用 ng 的表单 由于某些原因 我无法弄清楚提交按钮没有被禁用 除非所有三个输入字段都有效 否则它应该被禁用 谢谢您的帮助 这是我的博客模板 div div class cont
  • 如何在 Google 电子表格中插入列?

    我想将新数据添加到工作表的开头 开头 所以我必须在工作表中添加一个新的 A1 列 但我找不到任何 PHP 的 API 示例 现在我用这个附加数据 body new Google Service Sheets ValueRange value
  • 如果未使用 scp 命令指定目标路径,则文件位置

    要将文件夹从本地计算机复制到我使用的服务器 scp r local folder user server path 现在我忘了第一次指定目标路径 scp r local folder user server 现在有人知道该文件夹是否已被复制
  • 如何在视频标签中播放AVI文件?

    我想知道是否可以让浏览器在一个文件中播放 AVI 文件video tag 我在网上找到的所有谈论它的内容都集中在 MP4 和 Ogg 格式 但没有人谈论 AVI 格式 我发现的唯一解决方案是放弃video标记并使视频可以使用 JW Play
  • Lua 如何创建可用于变量的自定义函数?

    对于像 io close 这样的方法 你可以像这样使用它 file close 有没有办法创建一个像这样工作的自定义函数 您可以在变量上调用它 对我来说 我尝试使用它通过使用 string find 查找空格来将参数与文本文件分开 所以在文
  • 如何在 Node.js 中进行 Base64 编码?

    Node js 是否有内置 Base64 编码 我问这个的原因是final from crypto只能输出十六进制 二进制或ASCII数据 例如 var cipher crypto createCipheriv des ede3 cbc e
  • 对于某些版本的 PHP,“未指定输入文件”

    我安装了多个版本的 PHP 我写的 基本上 它是一个 ApacheLounge 安装 在 Windows 10 上通过 FastCGI 与 PHP 进行通信 这曾经让我在不同的虚拟主机上同时运行这些 PHP 版本 Apache 通过 Fas
  • 如何可视化来自谷歌协议缓冲区的数据?

    我想使用谷歌协议缓冲区存储数据 另一种序列化格式也可以 然后有一个用户界面来浏览该数据 是否有 C 框架 API 可以让我做到这一点 例如 它可以使用protobuf的反射接口 然后将数据填充到Qt的QTableView 或从其他工具包 中
  • 从 C 中的 long 中提取单个数字

    我正在为我的 C 课程 第一门编程课程 做作业 作业的一部分是编写代码 让用户输入一个最多9位数的数字 程序需要判断这个数字是 递增 真递增 递减 真递减 增减 实减实增 不减不增 共7个选项 由于这是我们的第一个作业 我们不允许使用课堂上
  • 与 Jenkins 工作流程/管道并行运行阶段

    请注意 问题是基于旧的 现在称为 脚本化 管道格式 当使用 声明式管道 时 并行块可以嵌套在阶段块内 请参阅声明式管道 1 2 的并行阶段 https jenkins io blog 2017 09 25 declarative 1 我想知
  • Android 中卡片视图内带有三个点的小部件的名称是什么?

    带有三个点的小部件是什么 如何将其添加到我的应用程序中 这根本不是一个小部件 它是一个ImageButton 无边框风格 使用包含一个的溢出图标PopupMenu 如需文档教程访问http developer android com gui
  • ASP.NET-Core 2.0 在应用程序启动后添加/删除路由

    我需要添加 删除通过 IApplicaitonBuilder 在 Startup 类的 Configure 方法期间注册的自定义路由 启动后 我在 UseMvc 命令中调用 MapRoute 方法 将一堆自定义路由注册到我的控制器 这些路由
  • ListBox不显示绑定数据

    在我的 Xaml 中我有这个
  • 将 Bootstrap 导航栏中的元素居中

    无论我尝试什么 我都无法将 Bootstrap 导航栏中的某些内容居中 有什么解决方案吗 我尝试添加一个div 使用margin 0 auto or margin right auto margin left auto used cente
  • opencv中的矩阵类型转换

    我正在尝试使用滤波器对图像进行卷积 并借助 opencv 中的 filter2D 函数将其存储到 CV 64F 类型的矩阵中 但目标矩阵的类型发生了变化 我尝试借助 allocateTo 0r ConvertTo 函数将其更改回 CV 64
  • 了解随机起始权重对神经网络性能的影响

    使用 R 和包neuralnet 我尝试对数据进行建模 如下所示 这些是几天内以 10 分钟为间隔的温度读数 上面是 2 天的截图 使用下面的代码 我将神经网络拟合到数据 可能有更简单的方法来对这些精确数据进行建模 但将来数据可能看起来完全
  • 无需安装即可使用Python

    我有一个安装程序 它使用 Python 脚本来安装多个组件 我不想在用户计算机上安装 Python 如果用户还没有安装 Python 并且我也不希望安装 Python 成为使用我的安装程序的先决条件 有没有一种方法可以在不使用安装程序的情况
  • 范围之间的随机日期时间 - 不统一输出

    我实现了下面的 RandomDate 但我总是不断获取接近 From 日期的值 我可能在这里错过了一些东西 public static DateTime GetRandomDate DateTime from DateTime to var
  • 为什么矢量化通常比循环更快?

    为什么在执行操作的硬件的最低级别和所涉及的一般底层操作 即 运行代码时所有编程语言的实际实现通用的事情 矢量化通常比循环快得多 计算机在循环时会做什么而在使用矢量化时不会做什么 我指的是计算机执行的实际计算 而不是程序员编写的计算 或者它有