python从浮点元组列表中构建交流数组的最快方法是什么?

rnd*_*nch 6 python ctypes pyopengl

上下文:我的Python代码将2D顶点数组传递给OpenGL.

我测试了两种方法,一种是ctypes,另一种是结构,后者是两倍以上.

from random import random
points = [(random(), random()) for _ in xrange(1000)]

from ctypes import c_float
def array_ctypes(points):
    n = len(points)
    return n, (c_float*(2*n))(*[u for point in points for u in point])

from struct import pack
def array_struct(points):
    n = len(points)
    return n, pack("f"*2*n, *[u for point in points for u in point])
Run Code Online (Sandbox Code Playgroud)

还有其他选择吗?有关如何加速此类代码的任何提示(是的,这是我的代码的一个瓶颈)?

Jon*_*ley 2

你可以试试 Cython。对我来说,这给出了:

function       usec per loop:
               Python  Cython
array_ctypes   1370    1220
array_struct    384     249
array_numpy     336     339
Run Code Online (Sandbox Code Playgroud)

因此,Numpy 仅在我的硬件(运行 WindowsXP 的旧笔记本电脑)上提供 15% 的好处,而 Cython 提供约 35% 的好处(在分布式代码中没有任何额外的依赖)。

如果您可以放宽每个点都是浮点元组的要求,并且只需将“点”设置为浮点数的扁平列表:

def array_struct_flat(points):
    n = len(points)
    return pack(
        "f"*n,
        *[
            coord
            for coord in points
        ]
    )

points = [random() for _ in xrange(1000 * 2)]
Run Code Online (Sandbox Code Playgroud)

那么结果输出是相同的,但时间进一步缩短:

function            usec per loop:
                    Python  Cython
array_struct_flat           157
Run Code Online (Sandbox Code Playgroud)

如果比我聪明的人想在代码中添加静态类型声明,Cython 也可能比这更好。(运行“cython -a test.pyx”对此非常有用,它会生成一个 html 文件,向您显示代码中最慢的(黄色)纯 Python 位置,以及已转换为纯 C 的 Python(白色)位置。这就是为什么我将上面的代码分散到很多行中,因为着色是每行完成的,所以它有助于像这样分散它。)

完整的 Cython 说明位于: http://docs.cython.org/src/quickstart/build.html

Cython 可能会在整个代码库中产生类似的性能优势,并且在理想条件下,应用适当的静态类型,可以将速度提高十到一百倍。