解析二进制数据时优化 Python 中的嵌套循环
Optimization of nested loop in Python while parsing binary data
我必须解析一些二进制文本,以十六进制小数表示,例如代码中的 hex_bytes以下。在这个例子中,有 32 个变量和 3 个点,这意味着我有 32 个变量重复了 3 次。
hex_bytes 一次包含 32 个变量的值,之后又一次,也是第三次。
问题是我需要以双精度(8 字节)转换第一个变量,并以单精度(4 字节)转换所有其他变量。
我制作了一个数组(32 列和 3 行),我只用双精度转换值填充第一列,所有其他列用单精度值填充。
我有一个嵌套循环并且它可以工作,但我想知道是否有比嵌套循环更快的解决方案?我尝试使用 lambda() 函数,也尝试使用 zip(),但我无法在我的代码中适当地实现它们。我在实现 8 或 16 增量时遇到问题。
代码如下:
import binascii
from struct import *
import numpy as np
hex_bytes = b'00000000000000000000a040000000000000a0401264062c321bd3ac00000000321bd32c00d42fae0000000000d42f2e0098412d00000000009841ad00e8192e0000000000e819ae93f9810200000000004060ae00000000ce14b02c66374a2e004e4aae000000000060afac00d42f2e00e819ae00000000ce14b02c321bd32c009841ad00000015316b673c0000a040000000000000a040b0422e2adf037fb6fef1d0349fe56436eebafcb5000080b3775d0236c6c915ad000000b35c09003386ad33b44d91be34157549b4b0ffe635cbcbe9b26edcb5b64d919e3405047fb68ba1b336be7229b44d919e344f9809b6775d0236157549b4fef1c03405047fb69fe564365c090033d0ee42f1df7ceb3d0000a040000000000000a0407d23202d26aaaab520a11034029698350bf228b594338d2bfaf128355681822e36641fac680c7bae200f70b3e44ffe33534886b3cf001c35c18d1cb2ed1cf4b57150fe331ca8aab5fe0eed35b56786b37150fe33fcf237b5faf12835534886b380a010341ca8aab502969835680c7baed76617efa79df43d0000a040000000000000a040e44c2b2d2cf7eead4541acab40bbf92d5b069bae0b81982b57a4982ea8f4752e73e02caca0266baee6ee462e7be754aafe1946ae2848b9a6563776ab00070baf36c87b2b22f2fc2d2713d72e4fa0d8ae36c87b2ba03bdead57a4982efe1946ae8b8081ac22f2fc2d40bbf92da0266bae48afbc9af2d77a3e0000a040000000000000a0402369062c7bb5d3acc84c84a8c739d42cd6e42fae74f268a9131f302e9ce0412d7ace14a9cd4b41ad71f5192eb0e04b263cf619ae35d644250000c028002060aef2c265a9bd0bb02c4ca64a2e30494aaef2c265a92e7bafac131f302e3cf619aedef456a9bd0bb02cc739d42ccd4b41ad65698779f6d77a3e0600a040e02d903a0000a0404351ec315a6a873458567135c3859ab52db5d2384888be399335f3b9f38988b4cacb7035d1862cb57179d6b8a30cbe39476e88b9f6fa0f31754a3eba18d0f339754a3e3a83cc0fb119d0f3b98ac488b9754a3e3aee10f1b59335f3b9476e88b91111f13583cc0fb1c3859ab5d1862cb5'
NoPoints = 3
NoVariables = 32
Values = np.zeros((NoPoints,NoVariables))
BinaryStart = 0
for NoPt in range(NoPoints):
for NoVar in range(NoVariables):
if NoVar == 0:
Values[NoPt,NoVar], = unpack('d', binascii.a2b_hex(hex_bytes[BinaryStart:BinaryStart+16]))
BinaryStart +=16
else:
Values[NoPt,NoVar], = unpack('f', binascii.a2b_hex(hex_bytes[BinaryStart:BinaryStart+8]))
BinaryStart += 8
注意8个二进制字符代表4个字节,16个二进制字符代表8个字节(这就是代码中出现8和16的原因)
我不知道它是否比嵌套循环快,但我们可以通过构造适当的解包格式字符串并一次解包来实现没有循环的情况:
Values = np.array(unpack('='+('d'+str(NoVariables-1)+'f')*NoPoints, binascii.a2b_hex(hex_bytes)))\
.reshape((NoPoints, NoVariables))
需要格式字符串的第一个字符 =
以防止 f
和 d
之间的对齐填充。
我必须解析一些二进制文本,以十六进制小数表示,例如代码中的 hex_bytes以下。在这个例子中,有 32 个变量和 3 个点,这意味着我有 32 个变量重复了 3 次。 hex_bytes 一次包含 32 个变量的值,之后又一次,也是第三次。 问题是我需要以双精度(8 字节)转换第一个变量,并以单精度(4 字节)转换所有其他变量。
我制作了一个数组(32 列和 3 行),我只用双精度转换值填充第一列,所有其他列用单精度值填充。
我有一个嵌套循环并且它可以工作,但我想知道是否有比嵌套循环更快的解决方案?我尝试使用 lambda() 函数,也尝试使用 zip(),但我无法在我的代码中适当地实现它们。我在实现 8 或 16 增量时遇到问题。
代码如下:
import binascii
from struct import *
import numpy as np
hex_bytes = b'00000000000000000000a040000000000000a0401264062c321bd3ac00000000321bd32c00d42fae0000000000d42f2e0098412d00000000009841ad00e8192e0000000000e819ae93f9810200000000004060ae00000000ce14b02c66374a2e004e4aae000000000060afac00d42f2e00e819ae00000000ce14b02c321bd32c009841ad00000015316b673c0000a040000000000000a040b0422e2adf037fb6fef1d0349fe56436eebafcb5000080b3775d0236c6c915ad000000b35c09003386ad33b44d91be34157549b4b0ffe635cbcbe9b26edcb5b64d919e3405047fb68ba1b336be7229b44d919e344f9809b6775d0236157549b4fef1c03405047fb69fe564365c090033d0ee42f1df7ceb3d0000a040000000000000a0407d23202d26aaaab520a11034029698350bf228b594338d2bfaf128355681822e36641fac680c7bae200f70b3e44ffe33534886b3cf001c35c18d1cb2ed1cf4b57150fe331ca8aab5fe0eed35b56786b37150fe33fcf237b5faf12835534886b380a010341ca8aab502969835680c7baed76617efa79df43d0000a040000000000000a040e44c2b2d2cf7eead4541acab40bbf92d5b069bae0b81982b57a4982ea8f4752e73e02caca0266baee6ee462e7be754aafe1946ae2848b9a6563776ab00070baf36c87b2b22f2fc2d2713d72e4fa0d8ae36c87b2ba03bdead57a4982efe1946ae8b8081ac22f2fc2d40bbf92da0266bae48afbc9af2d77a3e0000a040000000000000a0402369062c7bb5d3acc84c84a8c739d42cd6e42fae74f268a9131f302e9ce0412d7ace14a9cd4b41ad71f5192eb0e04b263cf619ae35d644250000c028002060aef2c265a9bd0bb02c4ca64a2e30494aaef2c265a92e7bafac131f302e3cf619aedef456a9bd0bb02cc739d42ccd4b41ad65698779f6d77a3e0600a040e02d903a0000a0404351ec315a6a873458567135c3859ab52db5d2384888be399335f3b9f38988b4cacb7035d1862cb57179d6b8a30cbe39476e88b9f6fa0f31754a3eba18d0f339754a3e3a83cc0fb119d0f3b98ac488b9754a3e3aee10f1b59335f3b9476e88b91111f13583cc0fb1c3859ab5d1862cb5'
NoPoints = 3
NoVariables = 32
Values = np.zeros((NoPoints,NoVariables))
BinaryStart = 0
for NoPt in range(NoPoints):
for NoVar in range(NoVariables):
if NoVar == 0:
Values[NoPt,NoVar], = unpack('d', binascii.a2b_hex(hex_bytes[BinaryStart:BinaryStart+16]))
BinaryStart +=16
else:
Values[NoPt,NoVar], = unpack('f', binascii.a2b_hex(hex_bytes[BinaryStart:BinaryStart+8]))
BinaryStart += 8
注意8个二进制字符代表4个字节,16个二进制字符代表8个字节(这就是代码中出现8和16的原因)
我不知道它是否比嵌套循环快,但我们可以通过构造适当的解包格式字符串并一次解包来实现没有循环的情况:
Values = np.array(unpack('='+('d'+str(NoVariables-1)+'f')*NoPoints, binascii.a2b_hex(hex_bytes)))\
.reshape((NoPoints, NoVariables))
需要格式字符串的第一个字符 =
以防止 f
和 d
之间的对齐填充。