【问题标题】:Processing a byte string in chunks分块处理字节字符串
【发布时间】:2020-12-05 06:27:38
【问题描述】:

我有一个非常长的字节串,比如这个(实际值可能是随机的):

in_var = b'\x01\x02\x03\x04\x05\x06...\xff'

我还有一个函数,它对一大块字节执行操作并返回相同数量的字节(本例中假设为 10 个字节):

def foo(chunk):
  # do smth with chunk
  # ......
  return chunk

我想处理 in_varfoo() 处理所有 10 字节的块(如果最后剩余的字节少于 10 字节,则按原样发送最后一个块)并使用输出创建一个新变量 out_var

我目前的做法耗时太长:

out_var = b''
for chunk in range(0, len(in_var), 10):
    out_var += foo(in_var[chunk: chunk + 10])

函数foo() 每次运行只需要几分之一秒,所以总数应该非常快(总共 10 个块)。但是,我的时间要长一个数量级。

我也尝试过类似的结果:

import numpy as np
import math
in_var= np.array_split(np.frombuffer(in_var, dtype=np.uint8), math.ceil(len(in_var)/10))
out_var= b"".join(map(lambda x: foo(x), in_var))

foo() 在这个例子中只能处理 10 个字节(例如:它是一个具有固定块大小的加密函数),如果给它一个较小的块,它只是填充以使块 10 个字节。假设我无法控制它,foo() 只能处理 10 个字节的块。

有没有更快的方法来做到这一点?作为最后的手段,我可​​能不得不并行化我的代码,以便并行处理所有块......

谢谢!


更新:

显然我没有正确测量foo() 花费的时间。事实证明,foo() 占用了大部分时间,因此上面的评论数量级。再次感谢您的 cmets 和建议,但我确实做了一些改进。并行化代码似乎是正确的前进道路。

【问题讨论】:

  • out_var += foo(in_var[chunk: chunk + 10]) 重复的字符串连接很慢。
  • 为什么要故意破坏性能,一次只调用 10 个字节的函数,而您可以执行更大的块? naive 解决方案比你复杂的解决方案快得多,我不得不想象你已经想到了一些你不能使用 fast naive 解决方案的原因,但你还没有告诉我们。
  • @JohnZwinck 假设我无法控制 foo(),它一次只能处理 10 个字节。我已经编辑了我的问题以明确说明

标签: python numpy chunks


【解决方案1】:

for 循环的问题在于它会创建一个新字符串,每次稍长一些,并将旧数据复制到新数据中。您可以通过预先分配字节并直接复制它们来加快速度:

out_var = bytearray(len(in_var))
for chunk in range(0, len(in_var), 10):
    out_var[chunk: chunk + 10] = foo(in_var[chunk: chunk + 10])

【讨论】:

  • 这有两个错误:1.TypeError: unsupported operand type(s) for //: 'bytes' and 'int' 和 2.TypeError: 'bytes' object does not support item assignment。第一个是通过在第一个乘法周围添加 () 来修复的:out_var = b' ' *(len(in_var) // 10 * 10)
  • @ItM:你说得对,已编辑。请立即尝试。
  • 我更新了帖子。无论如何,感谢您的所有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-29
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-12
相关资源
最近更新 更多