Gil*_*ash 9 python performance
我有一个"字节"对象和一个"int"掩码,我想用我的掩码对所有字节做xor.我在大"字节"对象(~4096 KB)上反复执行此操作.
这是我的代码,它可以很好地工作,只是它非常占用CPU并且减慢了我的脚本:
# 'data' is bytes and 'mask' is int
bmask = struct.pack('!I', mask) # converting the "int" mask to "bytes" of 4 bytes
a = bytes(b ^ m for b, m in zip(data, itertools.cycle(bmask)))
Run Code Online (Sandbox Code Playgroud)
我能想到的最好的是这个,大约快20倍:
# 'data' is bytes and 'mask' is int
# reversing the bytes of the mask
bmask = struct.pack("<I", mask)
mask = struct.unpack(">I", bmask)[0]
# converting from bytes to array of "int"s
arr = array.array("I", data)
# looping over the "int"s
for i in range(len(arr)):
arr[i] ^= mask
# must return bytes
a = bytes(arr)
Run Code Online (Sandbox Code Playgroud)
我的问题是:
PS如果它有任何重要性,我使用的是Python 3.5
我不认为使用纯 Python 可以比你的算法更快。(但法比奥·委罗内塞的回答表明这不是真的)。您可以通过在列表理解中进行循环来节省一点时间,但随后需要将该列表转换回数组,并且该数组必须转换为字节,因此它使用更多的 RAM,但带来的好处可以忽略不计。
但是,您可以使用 Numpy使其更快。这是一个简短的演示。
from time import perf_counter
from random import randrange, seed
import array
import numpy as np
seed(42)
def timed(func):
''' Timing decorator '''
def wrapped(*args):
start = perf_counter()
result = func(*args)
stop = perf_counter()
print('{}: {:.6f} seconds'.format(func.__name__, stop - start))
return result
wrapped.__name__ = func.__name__
wrapped.__doc__ = func.__doc__
return wrapped
@timed
def do_mask_arr1(data, mask):
arr = array.array("I", data)
# looping over the "int"s
for i in range(len(arr)):
arr[i] ^= mask
return arr.tobytes()
@timed
def do_mask_arr2(data, mask):
arr = array.array("I", data)
return array.array("I", [u ^ mask for u in arr]).tobytes()
@timed
def do_mask_numpy(data, mask):
return (np.fromstring(data, dtype=np.uint32) ^ mask).tobytes()
@timed
def make_data(datasize):
''' Make some random bytes '''
return bytes(randrange(256) for _ in range(datasize))
datasize = 100000
mask = 0x12345678
data = make_data(datasize)
d1 = do_mask_arr1(data, mask)
d2 = do_mask_arr2(data, mask)
print(d1 == d2)
d3 = do_mask_numpy(data, mask)
print(d1 == d3)
Run Code Online (Sandbox Code Playgroud)
典型输出
make_data: 0.751557 seconds
do_mask_arr1: 0.026865 seconds
do_mask_arr2: 0.025110 seconds
True
do_mask_numpy: 0.000438 seconds
True
Run Code Online (Sandbox Code Playgroud)
在运行 Linux 的旧单核 32 位 2GHz 机器上使用 Python 3.6.0 进行测试。
我刚刚跑了一次datasize = 4000000,do_mask_numpy用了 0.0422 秒。
| 归档时间: |
|
| 查看次数: |
1178 次 |
| 最近记录: |