当前位置: 首页 > 知识库问答 >
问题:

为什么分配使用NP.empty而不是O(1)

长孙宜
2023-03-14
>>> timeit.timeit(lambda: np.empty(100000000 ), number=10000)
0.2733485999999914
>>> timeit.timeit(lambda: np.empty(1000000000), number=10000)
0.8293009999999867

共有1个答案

党星鹏
2023-03-14

首先,我尝试在我的各种尺寸的机器上重现这种行为。以下是原始结果:

np.empty(10**1)   # 421 ns ± 23.7 ns per loop    (on 7 runs, 1000000 loops each)
np.empty(10**2)   # 406 ns ± 1.44 ns per loop    (on 7 runs, 1000000 loops each)
np.empty(10**3)   # 471 ns ± 5.8 ns per loop     (on 7 runs, 1000000 loops each)
np.empty(10**4)   # 616 ns ± 1.56 ns per loop    (on 7 runs, 1000000 loops each)
np.empty(10**5)   # 620 ns ± 2.83 ns per loop    (on 7 runs, 1000000 loops each)
np.empty(10**6)   # 9.61 µs ± 34.2 ns per loop   (on 7 runs, 100000 loops each)
np.empty(10**7)   # 11.1 µs ± 17.6 ns per loop   (on 7 runs, 100000 loops each)
np.empty(10**8)   # 22.1 µs ± 173 ns per loop    (on 7 runs, 10000 loops each)
np.empty(10**9)   # 62.8 µs ± 220 ns per loop    (on 7 runs, 10000 loops each)
np.empty(10**10)  # => Memory Error

因此,您是对的:这不是O(1)(至少在我的Windows计算机和您的系统上)。请注意,不能在这么短的时间内(急切地)初始化这些值,因为这意味着RAM吞吐量超过127 Tb/s,而我的机器上显然没有这个数据。

对于np.empty,这意味着创建(分配)这个数组所用的时间为O(1)

./malloc.exe 10           # Average time:  41.815 ns (on 1 run, 1000000 loops each)
./malloc.exe 100          # Average time:  45.295 ns (on 1 run, 1000000 loops each)
./malloc.exe 1000         # Average time:  47.400 ns (on 1 run, 1000000 loops each)
./malloc.exe 10000        # Average time: 122.457 ns (on 1 run, 1000000 loops each)
./malloc.exe 100000       # Average time: 123.032 ns (on 1 run, 1000000 loops each)
./malloc.exe 1000000      # Average time:   8.351 us (on 1 run, 1000000 loops each)
./malloc.exe 10000000     # Average time:   9.342 us (on 1 run, 100000 loops each)
./malloc.exe 100000000    # Average time:  18.972 us (on 1 run, 10000 loops each)
./malloc.exe 1000000000   # Average time:  64.527 us (on 1 run, 10000 loops each)
./malloc.exe 10000000000  # => Memory error

而且,大多数操作系统(OS)都有多个内存池。Linux、MacOS和Windows将虚拟内存分割成小页(通常为4KB)。由于在处理GB/TB的分配数据时,处理太小的页会带来很大的开销,因此这些操作系统还提供称为超级页或巨页的大页(通常为2MB到很少GB)。操作系统中所采用的路径可以根据分配的内存数量而改变,大多数操作系统都是为分配小块虚拟内存而不是大块虚拟内存而进行优化的。

请注意,用于管理系统内存的数据结构的大小通常受RAM大小的限制,而RAM在运行时通常是恒定的。此外,在给定的操作系统中用于管理内存碎片的算法的复杂性可能在理论上O(1)(或接近于此)。因此,有些人认为分配/释放数据是在恒定时间内完成的。但这是有争议的,因为人们应该考虑实际结果,而不仅仅是理论上的渐近界限。

有关更多信息,您可以查看以下帖子:

    null
 类似资料:
  • 问题内容: 的OpenJDK代码包括以下行: 为什么在这里使用,而不是?我很好奇。 问题答案: 要强调的是,数字是2的幂,而不是一个完全任意的选择。因此,它警告开发人员尝试不同的数字,他们应该在模式中使用其他数字(例如或,而不是),这样他们就不会破坏依赖于两个要求的幂的方法。有评论略高于: 任何一个的容量(表长度)始终是2的幂。之所以这样设计,是因为它允许使用快速的按位AND操作()将每个键的哈希

  • 很多人问了此问题,说bzero已经被posix-2008废弃,为何还使用bzero。选择bzero而不是memset,有2个原因: bzero有2个参数,指针和长度,很明确就是将制定size的内存初始化为0。而memset有3个参数,需要记忆参数的位置,有不少人经常把长度和初始化值搞错。 bzero比memset的可读性要好。memset可以制定初始化的值,实际上绝大多数情况都是0。 一旦新版本g

  • 问题内容: 我不确定为什么列出项目时为什么需要使用ul-li而不是简单地使用div。我可以使两者看起来完全一样,因此与创建div相比,创建无序列表的功能优势在哪里? 问题答案: 为了语义正确。HTML具有表达事物列表的功能,它可以帮助Google机器人,屏幕阅读器以及所有不仅仅关心网站外观的用户更好地了解您的内容。

  • 我花了很多时间来解决这个问题。我是GRAILS和GROOVY中的begginer。我有一个名为“tms\u dev”的旧oracle数据库模式。此架构有一些表(例如checktypes表)。此外,我还有由GRAILS生成的域类Checktype和ChecktypesController类-controller。 此类具有列表方法: def列表(最大整数){ } 我还配置了Datasource。gr

  • 问题内容: 我想知道为什么Arrays类的sort方法要求一个Object []类型的参数。为什么参数不是Comparable []类型。如果不传递Comparable [],它将生成ClassCastException。 为什么… public static void sort(Object [] a) 而不是 public static void sort(Comparable [] a) ?

  • 问题内容: 我刚刚开始学习数据结构,并且在进行数组插入时想知道为什么数组插入的时间复杂度为O(n)而不是O(n + 1)? 在最佳情况下,当插入在最后时,时间复杂度为O(1)。我想我们正在考虑1插入元素,因为这里没有元素被移动。在最坏的情况下,假设我们必须移动n个元素然后插入新元素,那么时间时间复杂度是否应该为O(n + 1)?n用于移动元素,1用于插入。 非常感谢您的帮助。 问题答案: O(n)