简体   繁体   English

在Python中快速将bytearray转换为元组数组(不使用NumPy)

[英]In Python fast way to convert a bytearray to array of tuples (Without using NumPy)

I need to speed up the following code:- 我需要加快以下代码: -

index = 0
WIDTH = 1920
HEIGHT = 1080
for o in xrange(WIDTH * HEIGHT):
    outbuf[o] = (buffer[index], buffer[index+1], buffer[index+2])
    index += 3

Which converts a bytearray to an array of tuples, but is too slow, is there any way to make it faster without using numpy. 这将bytearray转换为元组数组,但速度太慢,有没有办法让它更快,而不使用numpy。

Building outbuf using the grouper recipe from itertools is almost twice as fast on my machine. 使用itertools石斑鱼配方构建outbuf的速度几乎是我机器的两倍。

This is the grouper function from the docs: 这是文档中的分组函数:

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)

This script compares timings for the function in the question, using grouper to populate outbuf and using grouper to return outbuf rather than populating an external list. 这个脚本比较问题中函数的时间,使用石斑鱼填充outbuf并使用石斑鱼返回outbuf而不是填充外部列表。 The fastest method is to return outbuf from the function. 最快的方法是从函数返回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

Here are the timings for 50 repetitions of each approach: 以下是每种方法重复50次的时间:

OP function
39.3345730305

Fill external outbuf with grouper
30.0249710083

Return outbuf using grouper
20.357350111

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM