将数组初始化为0需要多长时间?

时间:2017-10-13 16:30:38

标签: c arrays initialization time-complexity

我是否感到困惑 int arr[n]={0}需要恒定的时间,即O(1)或O(n)?

2 个答案:

答案 0 :(得分:2)

你应该期待O(N)时间,但有一些警告:

  • 如果数组占用的内存小于字大小,则为O(1)。 (它可能是O(1)一直到现代CPU上的缓存行大小)
  • 如果数组适合内存中的单个层,则为O(N)。
  • 如果数组推送层是很复杂的:所有现代计算机上都有多个层(寄存器,L0缓存,L1缓存,L3缓存?,多CPU机器上的NUMA,虚拟内存(映射到交换),. ..)。如果数组不能合适 - 那将会造成严重的性能损失。

CPU缓存架构会严重影响将内存清零所需的时间。在实践中,调用O(N)有点误导,因为如果它落在缓存边界(线或整体)上,从100到101可能会增加10倍的时间。如果涉及交换,可能会更加引人注目。小心分层内存模型...

答案 1 :(得分:1)

通常,非静态存储的初始化为零是存储大小的线性。如果您正在重复使用该数组,则每次都需要将其置零。有些计算机体系结构试图通过维护页面或缓存行上的位掩码以及在缓存填充或加载单元机器中的某些点返回零来使其自由。这些有点罕见,但如果性能至关重要,通常可以在软件中复制效果。

可以说,归零的静态存储是免费的,但实际上备份它的页面会出现故障,并且在大多数架构上会有一些成本将它们归零。

(最终可能会出现提供零填充页面的故障成本非常明显的情况。例如重复malloc /没有大于某个阈值的块可能导致支持分配的地址空间返回到OS然后,出于安全原因操作系统必须将其归零,即使malloc不能保证返回零填充存储。更糟糕的是,程序在从malloc返回之后将零写入同一块中,因此它最终会被归为两次费用。)

对于以稀疏方式访问大多数零的大数组的情况,上面提到的零填充按需行为可以将实际使用的页数的成本降低到线性,而不是总大小。安排这样做通常需要直接使用mmap或类似的,而不仅仅是在C中分配一个数组而不是初始化它。