为什么迭代 std::array 比迭代 std::vector 快得多?

2024-01-05

编者注:
启用优化的后续问题仅对循环进行计时:
为什么迭代“std::vector”比迭代“std::array”更快? https://stackoverflow.com/questions/57125253/why-is-iterating-though-stdvector-faster-than-iterating-though-stdarray
我们可以看到延迟分配页面错误在读取未初始化的 BSS 内存与在定时循环之外初始化的动态分配+写入内存时的影响。


我尝试分析这段代码:

#include <vector>
#include <array>
#include <stdio.h>

using namespace std;

constexpr int n = 400'000'000;
//vector<int> v(n);
array<int, n> v;

int main()
{
    int res = 0;
    for(int x : v)
        res += x;
    printf("%d\n", res);
}

在我的机器上,array版本快于vector.

在这种情况下,内存分配是无关紧要的,因为它只分配一次。

$ g++ arrVsVec.cpp -O3
$ time ./a.out
0

real    0m0,445s
user    0m0,203s
sys 0m0,238s
$ g++ arrVsVec.cpp -O3
$ time ./a.out
0

real    0m0,749s
user    0m0,273s
sys 0m0,476s

我发现反汇编要复杂得多std::vector: https://godbolt.org/z/111L5G https://godbolt.org/z/111L5G


优化答案(g++ -O2):

您没有使用最终结果,因此编译器可以自由地优化整个循环。

这就是发生在array case https://gcc.godbolt.org/z/eLBTXI.

main:
        xor     eax, eax
        ret

But the vector分配和释放堆内存,这使优化变得复杂,并且编译器倾向于谨慎行事将其留在原处 https://gcc.godbolt.org/z/urlnh9:

main:
        xor     eax, eax
        ret
_GLOBAL__sub_I_v:
        sub     rsp, 8
        mov     edi, 400000000
        mov     QWORD PTR v[rip], 0
        mov     QWORD PTR v[rip+8], 0
        mov     QWORD PTR v[rip+16], 0
        call    operator new(unsigned long)
        lea     rdx, [rax+400000000]
        mov     QWORD PTR v[rip], rax
        mov     QWORD PTR v[rip+16], rdx
.L6:
        mov     DWORD PTR [rax], 0
        add     rax, 4
        cmp     rdx, rax
        jne     .L6
        mov     QWORD PTR v[rip+8], rdx
        mov     esi, OFFSET FLAT:v
        mov     edx, OFFSET FLAT:__dso_handle
        mov     edi, OFFSET FLAT:_ZNSt6vectorIiSaIiEED1Ev
        add     rsp, 8
        jmp     __cxa_atexit

所以这就是为什么array在这种特殊情况下,版本更快。在更现实的应用程序中,差异不会那么显着,并且主要取决于堆分配/释放时间vector case.

优化关闭的答案(g++):

不要对未经优化的编译内容进行基准测试。

差异可能是由于vector迭代器未内联。因此,与数组访问相比,在调试中访问向量元素会更多地产生额外的间接寻址。

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

为什么迭代 std::array 比迭代 std::vector 快得多? 的相关文章

  • 获取 std::variant 当前持有的 typeid(如 boost::variant type())

    我已经从 boost variant 迁移到 std variant 但遇到了障碍 我在 boost type 中使用了一个很好的函数 它可以让你获取当前持有的 typeid 看https www boost org doc libs 1
  • 键盘加速器在 UWP 应用中停止工作

    我正在尝试将键盘加速器添加到 UWP 应用程序中的 CommandBar 菜单项 当应用程序启动时 这工作正常 但在我第一次打开溢出菜单后 加速器停止工作 这似乎不会发生在主要命令 菜单之外 上 只有溢出菜单内的辅助命令才会发生 此外 单击
  • 无法从 Web api POST 读取正文数据

    我正在尝试从新的 Asp Net Web Api 中的请求中提取一些数据 我有一个像这样的处理程序设置 public class MyTestHandler DelegatingHandler protected override Syst
  • 导出类时编译器错误

    我正在使用 Visual Studio 2013 但遇到了一个奇怪的问题 当我导出一个类时 它会抛出 尝试引用已删除的函数 错误 但是 当该类未导出时 它的行为会正确 让我举个例子 class Foo note the export cla
  • Qt 计算和比较密码哈希

    目前正在 Qt 中为测验程序构建面向 Web 的身份验证服务 据我了解 在数据库中存储用户密码时 必须对其进行隐藏 以防落入坏人之手 流行的方法似乎是添加的过程Salt https en wikipedia org wiki Salt cr
  • 矩阵向量变换

    我正在编写一个代码来制作软件蒙皮器 骨骼 皮肤动画 并且我正处于 优化 阶段 蒙皮器工作得很好 并且在 Core 上 1 09 毫秒内对 4900 个三角形网格与 22 个骨骼进行蒙皮Duo 2 Ghz 笔记本 我需要知道的是 1 有人可以
  • 如何使用 wpf webbrowser 将数据发布到 Web 服务器

    我想从数据库获取数据并使用它来让用户登录到网站 我有一个包含 Web 浏览器控件的 wpf 页面 我有这样的代码 用于将用户登录到用 php 编写的网站
  • Docker DNS 设置

    我尝试使用自定义网络和 dos 设置创建 docker 容器 docker网络创建 driver bridge opt com docker network bridge enable ip masquerade true opt com
  • 在 Ubuntu 上纯粹通过 bash 脚本安装 mysql 5.7

    我想要一个无需任何手动输入即可安装 MySQL 5 7 实例的 bash 脚本 我正在关注数字海洋教程 https www digitalocean com community tutorials how to install mysql
  • 在 MATLAB 中创建共享库

    一位研究人员在 MATLAB 中创建了一个小型仿真 我们希望其他人也能使用它 我的计划是进行模拟 清理一些东西并将其变成一组函数 然后我打算将其编译成C库并使用SWIG https en wikipedia org wiki SWIG创建一
  • 指向字节数组的指针

    由于 Misra C 的要求 我的一位同事想要使用指针声明 但我遇到了一些问题 Misra 安全关键指南 不会让我们纯粹的程序员使用指针 但会让我们对数组字节进行操作 他打算获取一个指向字节数组的指针 因此我们不会在堆栈上传递实际的数组 T
  • 防止GDB中的PLT(过程链接表)断点

    在最新版本的 GDB 中 在库函数调用上设置断点会导致多个实际断点 调用过程链接表 PLT 实际的函数调用 这意味着当调用库函数时 我们每次都会经历两次中断 在以前的 GDB 版本中 只会创建 2 因此您只能得到一次中断 那么问题来了 是否
  • 格式化货币

    在下面的示例中 逗号是小数点分隔符 我有这个 125456 89 我想要这个 125 456 89 其他示例 23456789 89 gt 23 456 789 89 Thanks 看看这个例子 double value 12345 678
  • 以编程方式更新 ClickOnce 应用程序的部署清单会导致缺少 4.0 中所需的 <兼容框架> 元素

    我正在致力于自动化 NET 4 0 ClickOnce WPF 应用程序的安装程序 该应用程序需要在应用程序配置文件 我经历了寻找必须遵循的具体步骤的棘手过程Mage exe http msdn microsoft com en us li
  • 在简单注入器中注册具有多个构造函数和字符串依赖项的类型

    我正在尝试弄清楚如何使用 Simple Injector 我在项目中使用了它 注册简单服务及其组件没有任何问题 但是 当组件具有两个以上实现接口的构造函数时 我想使用依赖注入器 public DAL IDAL private Logger
  • 允许使用什么类型的内容作为 C 预处理器宏的参数?

    老实说 我很了解 C 编程语言的语法 但对 C 预处理器的语法几乎一无所知 尽管我有时在编程实践中使用它 所以问题来了 假设我们有一个简单的宏 它扩展为空 define macro param 可以放入宏调用构造中的语法有哪些限制 调用宏时
  • 错误左值需要作为赋值C++的左操作数

    整个程序基本上只允许用户移动光标 如果用户位于给定的坐标范围 2 2 内 则允许用户键入输入 我刚刚提供了一些我认为足以解决问题的代码 我不知道是什么导致了这个问题 你能解释一下为什么会发生吗 void goToXY int int 创建一
  • 使用 foreach 循环和 XmlNodeList C# 将新节点附加到节点列表

    目前我处理的是这样的XML类型 XML FILE http 20drive google com open id 0By5BxgNi9eGcRldxcEZNU0FDTzQ 参考XML文件 我想检查一个节点 如果找不到该节点 我必须将该节点附
  • #pragma pack(16) 和 #pragma pack(8) 的效果总是相同吗?

    我正在尝试使用来对齐数据成员 pragma pack n http msdn microsoft com en us library 2e70t5y1 28v vs 100 29 aspx 以下面为例 include
  • 从有符号字符转换为无符号字符然后再转换回来?

    我正在使用 JNI 并有一个 jbyte 类型的数组 其中 jbyte 表示为有符号字符 即范围从 128 到 127 jbyte 表示图像像素 对于图像处理 我们通常希望像素分量的范围为0到255 因此 我想将jbyte值转换为0到255

随机推荐

  • 错误:找不到 vcvarsall.bat

    我尝试安装Python包dulwich https pypi python org pypi dulwich pip install dulwich 但我收到一条神秘的错误消息 error Unable to find vcvarsall
  • Jquery Serialize 仅适用于 IE

    有了这个 我列出了我的代码 它在所有浏览器中都可以正常工作 但在 IE 中却不行 我在堆栈溢出中搜索了解决方案 但仍然无法修复 请有人帮助我吗 this serialize 在 IE 中返回空 Form UserTripSearch liv
  • 如何在主线程中获取异步结果

    我正在 Windows Phone 7 应用程序上制作登录页面 当异步线程上的服务器返回登录错误消息时 我想在登录页面上获取登录错误状态代码 所以我的问题是 在下面的代码示例中 请告诉我如何在 Main 方法中获取 响应字符串 字符串 ht
  • 从 C# 应用程序中的配置文件检索值不起作用

    当我尝试使用配置文件时遇到问题 我在这里和其他地方读过一些帖子 但工作上的问题却解决不了 在我的问题中 我添加了配置
  • 元素矩阵乘法:R 与 Rcpp(如何加速此代码?)

    我是新来的C 编程 使用Rcpp无缝集成到R 并且我希望得到一些有关如何加快某些计算速度的建议 考虑以下示例 testmat lt matrix 1 9 nrow 3 testvec lt 1 3 testmat testvec 1 2 3
  • CryptographicException:密钥在指定状态下使用无效

    我是 C 新手 我不明白为什么它会产生问题 CspParameters cspParams new CspParameters 24 cspParams KeyContainerName XML DISG RSA KEY RSACrypto
  • 出现错误:连接 ECONNREFUSED 127.0.0.1:3306

    我是 Node js 的初学者 正在学习有关如何为 Android 设置 Node js 服务器的教程 当我执行这个命令时 nodemon app js我收到这个错误 nodemon 1 19 0 nodemon to restart at
  • 相当于 Clojure 函数的 Java toString()

    我正在使用一些 Java 代码调用toString 在我的 Clojure 函数对象上 它返回类似的内容
  • 为什么在 Weblogic 集群中使用单播与组播

    从文档中并不清楚为什么应该在 WebLogic 集群中使用单播而不是多播 有人有使用这两者的经验以及迁移到 Unicast 的好处吗 单播和组播的主要区别如下 Unicast 假设集群中有三台服务器 MS 1 MS 2 MS 3 如果它们必
  • 如何跟踪 Node.js 中的(更改的)日志文件

    好吧 这似乎是一个简单的问题 但我无法从这里找到答案 因此我将其发布 希望有人可能遇到类似的问题 我需要监视指向 Web 服务器文件的符号链接 var log lighttpd error log更具体地说 感谢莱纳斯 G 蒂尔 https
  • WebElement.getCssValue 和 WebElement.getAttribute 用法

    任何人都可以帮助我了解如何使用这两个函数来获取任何 CSS 属性的值 如果有一个特定的 img 标签如下 img title Title alt myTitle src A B C xyz png driver getElement By
  • 在 QT 项目中使用 Crypto++ 静态库

    我已经在我的系统上静态构建了 cryptopp 它也通过了所有测试 这些是我在测试期间收到的警告 WARNING CRYPTOPP NO UNALIGNED DATA ACCESS is not defined in config h WA
  • 如何使用 Chrome 的调试器协议从时间戳导出 walltime?

    我一直在构建一个 Chrome 扩展程序 部分使用Chrome 调试器协议 https chromedevtools github io debugger protocol viewer 中的某些事件网络域 https chromedevt
  • 在 Xcode 中构建时添加变量

    我有一些动态值需要根据我在 Xcode 中进行的构建类型进行更改 我创建了2个方案DEV and PROD并在每个中设置环境变量 然后我在代码中使用它们 如下所示 var serviceDomain String let envVar Pr
  • 什么时候应该使用Task.Run()而不是await?

    我正在存储数据模型的状态 我克隆数据模型 然后希望将其异步写入 磁盘 我应该使用 Task Run 在后台线程上运行它吗 或者我应该将其设为异步函数而不是等待它 这将使其在 UI 线程上运行 与此类似 但我的问题有点不同 异步任务 使用 M
  • Android 使元素仅出现在纵向视图中

    我有一个支持广告的应用程序 因此 当屏幕旋转时 广告仍然存在 我希望能够使广告仅在手机处于纵向而不是横向时存在 我是否需要声明一个单独的景观 xml 或者是否有其他方法可以做到这一点 如果我需要声明一个横向 xml 我该如何在 java 中
  • C# 中的队列实现

    我正在处理一次只能处理 1 个命令的硬件资源 我将通过 Web 界面公开它的一些 API 函数 因此显然一次很有可能发送超过 1 个命令 我决定在提交这些命令时对其进行排队是确保串行处理的最佳方法 我计划在静态类中实现队列 Web 应用程序
  • Intellij Idea 日志 GradleConnectionException:构建时无法使用 Gradle 安装执行构建

    我使用 Intellij Idea 13 1 1 在构建时遇到 GradleConnectionException Error org gradle tooling GradleConnectionException Could not e
  • pty 和 tty 是什么意思?

    我注意到很多提到pty and tty在一些开源项目中 有人可以告诉我它们是什么意思以及它们之间有什么区别吗 tty原本的意思是 电传打字机 and pty means 伪电传打字机 在 UNIX 中 dev tty 是任何像 电传打字机
  • 为什么迭代 std::array 比迭代 std::vector 快得多?

    编者注 启用优化的后续问题仅对循环进行计时 为什么迭代 std vector 比迭代 std array 更快 https stackoverflow com questions 57125253 why is iterating thou