【问题标题】:Fill a bytearray of known size from generator从生成器填充一个已知大小的字节数组
【发布时间】:2021-04-02 20:37:23
【问题描述】:

从以前给定或计算的非常长的小字节数数组(MB、GB、TB)传出(所以我使用bytearray),我需要在下一个迭代步骤中计算后续bytearray .可以计算下一个迭代步骤bytearray 所需的大小,因此我可以使用bytearray 的构造函数之一预先分配内存:

# A is the current/former bytearray
# sizes of array: 1 -> 2 -> 8 -> 48 -> 480 -> 5_760 -> 92_160 -> 1_658_880 -> 
# 36_495_360 -> 1_021_870_080 -> 30_656_102_400 [ -> 1_103_619_686_400 ... ]
ls = NextLenArray(A)
L = bytearray(ls)

# generator will create new values out of the current existing
for i,j in enumerate(gen_values(A)):
    L[i] = j

# need to assign it back into A for next iteration
A = L

另外,很明显通过使用生成器内部理解直接创建下一个bytearray。我不知道如何以及何时(逐步?)保留内存。

A = bytearray(j for j in gen_values(A))

看起来它运行得快了一点,但是监控任务管理器在生成时会使用更多内存,并且在以后的迭代步骤中它会提前一步停止,原因是MemoryError

是否有一种简单的方法可以通过分配具有所需大小的bytearray 并将其与生成器/综合列表一起使用来组合预预留?

【问题讨论】:

    标签: arrays python-3.x performance out-of-memory


    【解决方案1】:

    看起来它运行得快了一点,但是监控任务管理器在生成时会使用更多内存,并且在以后的迭代步骤中它会提前一步停止,导致内存错误。

    这是因为生成器没有众所周知的长度。 Python 不能遍历生成器来知道它的长度,因为它会被消耗掉。所以它需要或多或少地动态调整字节数组的大小。关于实现(例如,大小不断增长的动态数组或独立大块的动态数组),这可能需要显着更多的内存,而不是直接在好大小。在我的机器上,使用 CPython 3.9.2,我无法重现您的问题,因为它使用内存高效实现。

    是否有一种简单的方法可以通过分配具有所需大小的字节数组并将其与生成器/理解列表一起使用来组合预先保留?

    是的,您可以使用基于块的副本。这是一个例子:

    import itertools
    
    ls = NextLenArray(A)
    L = bytearray(ls)
    gen = gen_values(A)
    chunkSize = 65536
    
    for i in range(0, ls, chunkSize):
        # Copy a chunk. This can (and does) allocate memory because of a 
        # potential internal copy. But the amount is bounded by the chunk size.
        L[i:i+chunkSize] = itertools.islice(gen, chunkSize)
    

    请注意,在纯 Python 中处理大量内存效率不高(尤其是在 CPython 中)。考虑使用高性能 Python 包,例如 Numpy 和 Numba,或者用 C 或 C++ 等本地语言编写一些部分(例如使用 Cython)。或者,您可能对使用 PyPy 感兴趣。

    【讨论】:

    • 谢谢 - 帮了很多忙 - 一个问题:一开始字节数组非常小,所以我用来定义大小:chunksize = min(65536, ls) - 我比较了一些不同长度的不同数字数组 - 看起来它不应该太小(1KB),但 1MB 块的性能并没有真正获胜 - 数据高达 1GB
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    • 2019-07-13
    • 1970-01-01
    • 2020-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多