使用cython序列化一组整数

时间:2018-01-21 20:12:05

标签: python serialization struct cython

我在Pyrobuf页面上看到了这个示例代码,用于序列化整数,比通过struct.pack快〜3倍:

def ser2(): 
    cdef int x = 42 
    return (<char *>&x)[:sizeof(int)]

我想知道如何为一组整数做这件事。 我看到cython有int[:]array.array类型,但我仍然不明白如何获取整数列表,例如,通过{{1}获得相同(但更快)的结果}。 struct.pack('i', *num_list)对我来说似乎没有那么快,我想知道应该怎么做。

1 个答案:

答案 0 :(得分:2)

我假设你想要加速以下(Python3):

import struct 
lst=list(range(100))  #any other size
struct.pack('i'*len(lst), *lst)

没有struct和cython你可以在python中实现它:

import array
bytes(array.array('i', lst))
然而,这比struct - 模块:

慢一些
>>> %timeit struct.pack('i'*len(lst), *lst)
2.38 µs ± 9.48 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
>>> %timeit bytes(array.array('i',lst))
3.94 µs ± 92 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

但是,cython可用于加速array的创建,文档请参阅here(arrays)here(str/bytes)

 %%cython
 import array
 from cpython cimport array
 def ser_int_list(lst):
    cdef Py_ssize_t n=len(lst)
    cdef array.array res=array.array('i')
    array.resize(res, n)  #preallocate memory
    for i in range(n):
       res.data.as_ints[i]=lst[i]            #lst.__get__() needs Python-Integer, so let i be a python-integer (not cdef)
    return res.data.as_chars[:n*sizeof(int)] # str for python2, bytes for python3

时间表显示以下表现:

#list_size    struct-code    cython-code    speed-up
     1           343 ns         238 ns        1.5
    10           619 ns         283 ns         2
   100          2.38 µs        2.38 µs        3.5
  1000          21.6 µs        5.11 µs         4
 10000           266 µs        47.5 µs        5.5 

即。 cython提供了一些加速,从1.5小列表到5.5大列表。

可能这可以进一步调整,但我希望你能得到这个想法。

测试代码:

import struct
for n in [1, 10,10**2, 10**3, 10**4]:
    print ("N=",n)
    lst=list(range(n))
    print("struct:")
    %timeit struct.pack('i'*len(lst), *lst)
    print("cython:")
    %timeit ser_int_list(lst)