在 C/C++ 中以 O(1) 时间初始化动态数组

2024-01-11

有没有办法在 O(1) 时间内初始化整个动态数组? 有没有类似的东西bool a[10] = {false}在静态数组的情况下?


对于动态数组,要设置的每个元素都必须由CPU单独考虑,因此时间复杂度为O(N).

或者是吗?

但这并不是“big-oh”真正的工作原理。这也不是 CPU 真正的工作方式。

Big-oh 表示法涉及渐进的当元素数量趋于无穷大时系统的行为。这就是说:当我们将其应用于少量元素时,我们应该持保留态度!

CPU 对于少量元素和大量元素的行为也不同,因为它们具有不同的缓存级别,这意味着不同的访问延迟。你看到这个每时每刻设计高性能算法。例如,参见这一页 https://github.com/flame/how-to-optimize-gemm/wiki#blocking-to-maintain-performance描述如何优化矩阵乘法:“阻塞以保持性能”部分主要是关于重新排列计算,以便它们保留在 CPU 的缓存中。

现在,让我们更具体地谈谈你的问题。

请考虑下面每个计算机科学家应该知道的延迟数字的方便图表(source https://gist.github.com/hellerbarde/2843375).

这里的重点是(随机)主内存引用成本约为 100ns,而对 L1 缓存的引用成本为 0.5ns,对 L2 缓存的引用成本为 7ns。由于缓存效应,从 RAM 中顺序读取可显着提高速度。

这意味着,在其他条件相同的情况下,您可以从 L1 读取 200 个数字,或者从 L2 读取 14 个数字,而所用的时间与从 RAM 中读取单个数字所需的时间相同。

这让我们进入成本模型。

考虑像这样初始化两个动态数组:

std::vector<int> a(20,1);
std::vector<int> a(21,1);

根据上述内容,我们预计处理附加元素大约需要 0.5 纳秒(因为整个数组适合缓存),而将数组存储到内存则需要 100 纳秒。也就是说,添加额外元素的边际成本可以忽略不计。事实上,即使添加许多元素的边际成本也可以忽略不计(多少取决于处理器)。

让我们应用这些想法。考虑这两个陈述。

int m = array1[20];
std::vector<int> a(900,1);

如果你从一个角度思考这个问题O(1) vs. O(N)从角度来看,您可能会认为有些愚蠢的事情,例如“第二个语句将比第一个语句花费 900 倍的时间”。您可能有一个更复杂的想法是“O(N)第二个语句可能很小,因此很难知道哪个会更快”。

有了一些缓存知识,您可能会对自己说“对于这些小N值渐近分析是不合适的”。您可能进一步认为“这些语句可能需要相同的时间”或“第二个语句可能会运行faster由于缓存效应,比第一个要好”。

一个实验

我们可以用一个简单的实验来证明这一点。

以下程序初始化不同长度的数组:

#include <vector>
#include <iostream>
#include <chrono>
#include <string>

int main(int argc, char **argv){
  const int len = std::stoi(std::string(argv[1]));
  auto begin = std::chrono::high_resolution_clock::now();
  for(int i=0;i<10000;i++){
    std::vector<int> a(len,1);
    (void)a;
  }
  auto end = std::chrono::high_resolution_clock::now();
  std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(end-begin).count() << std::endl; //Nanoseconds
}

该程序运行动态数组的多次初始化,以平均由于机器上运行的其他程序而导致的波动。

我们多次运行这个程序:

for n in {1..100}; do ./a.out 1; done | awk '{print "1 "$1}' | xclip

处理由于其他程序运行而导致的程序启动和机器内存状态的差异。

在我的 Intel(R) Core(TM) i5 CPU M480 @ 2.67GHz 上,具有 32K L1 缓存、256K L2 缓存和 3072K L3 缓存,结果是这样的:

请注意,对于大约 1000 个元素,小型数组的时间增长是次线性的(与较大数组上的后续行为相结合)。这不是O(N)行为。此后,添加 10 倍以上的元素会导致消耗约 10 倍的时间。这是O(N)行为。

在我的 Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz(具有 32K L1 缓存、256K L2 缓存和 30720K L3 缓存)上尝试相同的测试,得到了非常相似的结果:

底线

数组初始化位于O(N)因为它随着元素数量的增加而增长。但实际上,由于缓存的原因,cost不线性上升。因此,一个“O(1)“命令可能需要与”相同的时间O(N)“命令,取决于大小N.

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

在 C/C++ 中以 O(1) 时间初始化动态数组 的相关文章

  • 为什么这个 Web api 控制器不并发?

    我有一个 Web API 控制器 里面有以下方法 public string Tester Thread Sleep 2000 return OK 当我调用它 10 次 使用 Fiddler 时 我预计所有 10 次调用都会在大约 2 秒后
  • 在 CPP 类中将 C 函数声明为友元

    我需要在 C 函数中使用类的私有变量 我正在做这样的事情 class Helper private std string name public std getName return name friend extern C void in
  • 转换 const void*

    我有一个函数返回一个const void 我想用它的信息作为char 我可以将它投射为 C 风格的罚款 char variable但是当我尝试使用reinterpret cast like reinterpret cast
  • java中如何重新初始化int数组

    class PassingRefByVal static void Change int pArray pArray 0 888 This change affects the original element pArray new int
  • 不同 C++ 文件中的相同类名

    如果两个 C 文件具有相同名称的类的不同定义 那么当它们被编译和链接时 即使没有警告也会抛出一些东西 例如 a cc class Student public std string foo return A void foo a Stude
  • C++中判断unicode字符是全角还是半角

    我正在编写一个终端 控制台 应用程序 该应用程序应该包装任意 unicode 文本 终端通常使用等宽 固定宽度 字体 因此要换行文本 只需计算字符数并观察单词是否适合一行并采取相应的操作 问题是 Unicode 表中的全角字符在终端中占用了
  • 如何使用 x64 运行 cl?

    我遇到了和这里同样的问题致命错误 C1034 windows h 未设置包含路径 https stackoverflow com questions 931652 fatal error c1034 windows h no include
  • 是否使用 C# 数据集? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我对 C 中的数据集概念有点困惑 编码 ASP NET 站点 但这并不重要 在我的阅读中 我了解到它们 本质上 用作我的应用程序和我的
  • 如何在 C# 中创建异步方法?

    我读过的每一篇博客文章都会告诉您如何在 C 中使用异步方法 但由于某些奇怪的原因 从未解释如何构建您自己的异步方法来使用 所以我现在有这段代码使用我的方法 private async void button1 Click object se
  • Oauth2中如何同时撤销RefreshToken和使AccessToken失效

    我正在使用 Owin Oauth2 授权和资源服务器相同 开发单页面应用程序 AngularJS Net MVC Json Rest API 的身份验证流程 我选择了 Bearer Token 路由而不是传统的 cookie session
  • 比较:接口方法、虚方法、抽象方法

    它们各自的优点和缺点是什么 接口方法 虚拟方法 抽象方法 什么时候应该选择什么 做出这一决定时应牢记哪些要点 虚拟和抽象几乎是一样的 虚方法在基类中有一个实现 可以选择重写 而抽象方法则没有 并且must在子类中被覆盖 否则它们是相同的 在
  • 如何解压 msgpack 文件?

    我正在将 msgpack 编码的数据写入文件 在编写时 我只是使用 C API 的 fbuffer 如 我为示例删除了所有错误处理 FILE fp fopen filename ab msgpack packer pk msgpack pa
  • C++:为什么 numeric_limits 对它不知道的类型起作用?

    我创建了自己的类型 没有任何比较器 也没有专门化std numeric limits 尽管如此 由于某种原因 std numeric limits
  • 代码中的.net Access Forms身份验证“超时”值

    我正在向我的应用程序添加注销过期警报 并希望从我的代码访问我的 web config 表单身份验证 超时 值 我有什么办法可以做到这一点吗 我认为您可以从 FormsAuthentication 静态类方法中读取它 这比直接读取 web c
  • Visual Studio 2015 - Web 项目上缺少共享项目参考选项卡

    我从 MSDN 订阅升级到 Visual Studio 2015 因为我非常兴奋地阅读有关共享项目的信息 当我们想要做的只是重用代码时 不再需要在依赖项中管理 21382 个 nuget 包 所以我构建了一个测试共享项目 其中包含一些代码
  • 没有“对 *this”功能的右值引用的解决方法

    我有一个围绕可移动对象的代理容器类 并希望代理能够隐式生成对底层对象的右值引用 但仅当代理本身被移动时 我相信我将能够按照提案 n2439 实施此行为 将移动语义扩展到 this http www open std org jtc1 sc2
  • 是否允许全局静态标识符以单个 _ 开头?

    换句话说 可能static 文件范围 全局变量恰好以一个下划线开头 而不会产生与 C 实现发生名称冲突的可能性 https www gnu org software libc manual html node Reserved Names
  • 我可以使用 lambda 函数或 std::function 对象来代替函数指针吗?

    我有一个需要使用的库 它定义了以下内容 typedef void CallbackFunction const int i 并且有一个注册回调的函数 如下所示 void registerCallback CallbackFunction p
  • MySqlConnectionStringBuilder - 使用证书连接

    我正在尝试连接到 Google Cloud Sql 这是一个 MySql 解决方案 我能够使用 MySql Workbench 进行连接 我如何使用 C 连接MySqlConnectionStringBuilder 我找不到提供这三个证书的
  • 当用户更改 Windows 中的语言键盘布局时如何通知?

    I want to show a message to user when the user changes the language keyboard layout of Windows for example from EN to FR

随机推荐

  • 多边形斑点的中心线(二值图像)

    我有一个蠕虫的二进制图像 斑点提取效果很好 我有兴趣在斑点 蠕虫 上拟合中心线 到目前为止 我想出了这个 从多边形开始 在图像中提取斑点的轮廓之后 我应用了 voronoi 计算并丢弃了多边形 蓝色 之外的所有顶点 这给了我可以的黑色中心线
  • 如何在 Awesomium 中隐藏光标

    我试过这个
  • 如何在 Blazor 中获取客户端 IP 和浏览器信息?

    如何在 Blazor 服务器端获取 IP 地址和浏览器名称 版本等客户端信息 好吧 我今天早上遇到了这个问题 我为服务器端 Blazor 解决这个问题的方法是创建一个类 然后您可以将其作为作用域服务注入到 host cshtml 上 然后在
  • C++11 带有双参数的运算符""

    考虑 struct str str operator X long double d return str 使用 g 4 7 2 Wall std c 11 可以正常编译 但现在如果我给一个双倍 str operator X double
  • 有没有一种简单的方法可以按范围对 js 数组值进行分组?

    如果我有一个像下面这样的js数组 有没有一种简单的方法可以按范围重新分组数组值 逻辑是基于范围步长 范围步长是1 所以如果数组值连续增加1 那么应该写成 1 3 否则应该分到另一组 非常感谢 var list 1 2 3 5 6 9 12
  • 在 Android 上使用 C/C++ 库

    我编写了一个库 它通过 c c 编程语言提供了一些函数 add sub divide multi 它是使用Android NDK构建到library so中的 所以现在 我想使用Android来调用库的这些函数 我想要作为我该怎么办 Tha
  • fmap和bind的关系

    查找之后Control Monad https hackage haskell org package base 4 9 1 0 docs Control Monad html文档 我很困惑 这段话 上述法律意味着 fmap f xs xs
  • SSL 和证书密钥库

    我的 Java 程序如何知道包含证书的密钥库在哪里 或者 我如何告诉我的 Java 程序在哪里查找密钥库 以某种方式指定密钥库后 如何指定用于向客户端验证服务器的证书 SSL 属性是通过系统属性在 JVM 级别设置的 这意味着您可以在运行程
  • Firebase 上游云消息

    我已经使用设置了 XMPP 服务器这个节点JS https www npmjs com package node xcs包裹 我可以很好地发送下游消息 从 XMPP 服务器到设备 但是当我尝试发送上游消息时 服务器很少收到它 服务器上处理上
  • 无法从 git bash 运行节点

    我无法再从 git bash 终端运行节点 它可以通过 Git CMD 和标准 Windows CLI 运行 如果我尝试运行一个文件 例如node index js 或者甚至只是通过启动节点node 我返回到输入提示 但现在我看不到任何字符
  • lucene:如何执行增量索引并避免“删除和重做”

    我有一个文件夹 MY FILES 其中包含大约 500 个文件 每天都会有一个新文件到达并放置在那里 每个文件的大小约为 4Mb 我刚刚开发了一个简单的 void main 来测试是否可以在这些文件中搜索特定的通配符 它工作得很好 问题是我
  • Win7:无需重启即可更换驱动程序

    我正在 Windows 7 下调试音频驱动程序 当我需要用更新版本替换它时 我必须重新启动系统 因为尽管驱动程序已卸载 但 DriverStore 下的当前驱动程序副本仍被锁定 有没有办法避免重启 XP 上是可以的 你尝试过阻止司机吗dev
  • 通过 Lotus Notes 使用 java Apache Commons Mail 发送电子邮件

    我在使用 java 程序中的 Lotus Notes 发送电子邮件时遇到了电子邮件配置问题 我知道这非常简单 但我想我错过了一些东西 我的代码如下 import java util logging Level import java uti
  • 对参数包中的每个元素应用函数

    我有以下专门化的模板函数 Pass the argument through template
  • 输入新功能时 rsp 不会移动[重复]

    这个问题在这里已经有答案了 当进入 C 函数时 我希望在反汇编中看到堆栈指针如何被减去足以为变量腾出空间 但没有 我只看到当esp仍然指向ebp时如何通过ebp直接访问变量的地址 push rbp mov rsp rbp movl 0x4
  • 如何使用 Nuget 控制台获取 jQuery 版本列表?

    我正在尝试找出解决方法来解决我遇到的问题 jQuery 2 0 是 Nuget 希望通过 GUI 更新到的版本 我可以将 Nuget 保留在 jQuery 1 9 x 1 x 路径上 而不是升级到 2 x 吗 https stackover
  • 如何在Unity3d软键盘中检测“完成”按钮

    I use a InputField in my android app to get a string a soft keyboard pops up when i m entering a string but now i want t
  • R Shiny:如何更改表格的背景颜色

    我找到了如何更改 Shiny 中用户界面的背景颜色 我发现的提款是它还为我显示的表格的背景着色tableOutput 这里我展示了一个虚拟示例 ui R 闪亮的UI 页面带侧边栏 headerPanel 虚拟 侧边栏面板 标签 hr 主面板
  • undefined 不是一个对象(评估 'RNGestureHandlerModule.State'

    我已经安装了反应导航 in my 反应本机项目 它是一个入门项目 没有任何代码 但是在运行项目时我遇到了这样的错误 这是我的导航代码 import createStackNavigator from react navigation imp
  • 在 C/C++ 中以 O(1) 时间初始化动态数组

    有没有办法在 O 1 时间内初始化整个动态数组 有没有类似的东西bool a 10 false 在静态数组的情况下 对于动态数组 要设置的每个元素都必须由CPU单独考虑 因此时间复杂度为O N 或者是吗 但这并不是 big oh 真正的工作