Python 将字节数组转换为元组数组的快速方法(不使用 NumPy)
In Python fast way to convert a bytearray to array of tuples (Without using NumPy)
我需要加速以下代码:-
index = 0
WIDTH = 1920
HEIGHT = 1080
for o in xrange(WIDTH * HEIGHT):
outbuf[o] = (buffer[index], buffer[index+1], buffer[index+2])
index += 3
将字节数组转换为元组数组,但速度太慢,有没有办法在不使用 numpy 的情况下使其更快。
使用 itertools
中的 grouper recipe 构建 outbuf
在我的机器上几乎快两倍。
这是文档中的 grouper 函数:
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
此脚本比较问题中函数的计时,使用 grouper 填充 outbuf 并使用 grouper 填充 return outbuf 而不是填充外部列表。最快的方法是从函数return outbuf
.
from itertools import izip_longest
import random
import sys
import timeit
WIDTH = 1920
HEIGHT = 1080
buffer_ = bytearray(random.randint(0, 255) for _ in xrange(WIDTH * HEIGHT * 3))
# Function from the question
def extract(buffer_):
index = 0
for o in xrange(WIDTH * HEIGHT):
outbuf[o] = (buffer_[index], buffer_[index+1], buffer_[index+2])
index += 3
def grouper(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
# Use grouper with external outbuf
def grouper_extract(buffer_):
groups = grouper(buffer_, 3)
for o in xrange(WIDTH * HEIGHT):
outbuf[o] = next(groups)
# Return a list using grouper
def grouper_list(buffer_):
return list(grouper(buffer_, 3))
if __name__ == '__main__':
# Set number of timeit repetitions.
try:
number = int(sys.argv[1])
except IndexError:
number = 50
outbuf = [0 for _ in xrange(WIDTH * HEIGHT * 3)]
print 'OP function'
print timeit.timeit(setup="from __main__ import extract, outbuf, buffer_",
stmt="extract(buffer_)", number=number)
print
print 'Fill external outbuf with grouper'
print timeit.timeit(setup="from __main__ import grouper_extract, outbuf, buffer_",
stmt="grouper_extract(buffer_)", number=number)
print
print 'Return outbuf using grouper'
print timeit.timeit(setup="from __main__ import grouper_list, buffer_",
stmt="outbuf = grouper_list(buffer_)", number=number)
print
以下是每种方法重复 50 次的时间安排:
OP function
39.3345730305
Fill external outbuf with grouper
30.0249710083
Return outbuf using grouper
20.357350111
我需要加速以下代码:-
index = 0
WIDTH = 1920
HEIGHT = 1080
for o in xrange(WIDTH * HEIGHT):
outbuf[o] = (buffer[index], buffer[index+1], buffer[index+2])
index += 3
将字节数组转换为元组数组,但速度太慢,有没有办法在不使用 numpy 的情况下使其更快。
使用 itertools
中的 grouper recipe 构建 outbuf
在我的机器上几乎快两倍。
这是文档中的 grouper 函数:
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
此脚本比较问题中函数的计时,使用 grouper 填充 outbuf 并使用 grouper 填充 return outbuf 而不是填充外部列表。最快的方法是从函数return outbuf
.
from itertools import izip_longest
import random
import sys
import timeit
WIDTH = 1920
HEIGHT = 1080
buffer_ = bytearray(random.randint(0, 255) for _ in xrange(WIDTH * HEIGHT * 3))
# Function from the question
def extract(buffer_):
index = 0
for o in xrange(WIDTH * HEIGHT):
outbuf[o] = (buffer_[index], buffer_[index+1], buffer_[index+2])
index += 3
def grouper(iterable, n, fillvalue=None):
args = [iter(iterable)] * n
return izip_longest(fillvalue=fillvalue, *args)
# Use grouper with external outbuf
def grouper_extract(buffer_):
groups = grouper(buffer_, 3)
for o in xrange(WIDTH * HEIGHT):
outbuf[o] = next(groups)
# Return a list using grouper
def grouper_list(buffer_):
return list(grouper(buffer_, 3))
if __name__ == '__main__':
# Set number of timeit repetitions.
try:
number = int(sys.argv[1])
except IndexError:
number = 50
outbuf = [0 for _ in xrange(WIDTH * HEIGHT * 3)]
print 'OP function'
print timeit.timeit(setup="from __main__ import extract, outbuf, buffer_",
stmt="extract(buffer_)", number=number)
print
print 'Fill external outbuf with grouper'
print timeit.timeit(setup="from __main__ import grouper_extract, outbuf, buffer_",
stmt="grouper_extract(buffer_)", number=number)
print
print 'Return outbuf using grouper'
print timeit.timeit(setup="from __main__ import grouper_list, buffer_",
stmt="outbuf = grouper_list(buffer_)", number=number)
print
以下是每种方法重复 50 次的时间安排:
OP function
39.3345730305
Fill external outbuf with grouper
30.0249710083
Return outbuf using grouper
20.357350111