Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 水稻Cython编码_Python_Compression_Cython - Fatal编程技术网

Python 水稻Cython编码

Python 水稻Cython编码,python,compression,cython,Python,Compression,Cython,下面是众所周知的Rice编码(=Golomb code withM=2^k)的一个实现,它在Python中广泛用于压缩算法 不幸的是,它相当缓慢。造成这种低速的原因可能是什么?(StringIO?数据是逐字节写入的事实?) 为了加快编码速度,您建议使用什么你会用什么技巧来加快Cython的速度? import struct import StringIO def put_bit(f, b): global buff, filled buff = buff | (b <&l

下面是众所周知的Rice编码(=Golomb code with
M=2^k
)的一个实现,它在Python中广泛用于压缩算法

不幸的是,它相当缓慢。造成这种低速的原因可能是什么?(
StringIO
?数据是逐字节写入的事实?)

为了加快编码速度,您建议使用什么你会用什么技巧来加快Cython的速度?

import struct
import StringIO

def put_bit(f, b):
    global buff, filled
    buff = buff | (b << (7-filled))
    if (filled == 7):
        f.write(struct.pack('B',buff))
        buff = 0
        filled = 0
    else:
        filled += 1

def rice_code(f, x, k):
    q = x / (1 << k)                       
    for i in range(q): 
        put_bit(f, 1)
    put_bit(f, 0)
    for i in range(k-1, -1, -1):
        put_bit(f, (x >> i) & 1)

def compress(L, k):
    f = StringIO.StringIO()
    global buff, filled
    buff = 0
    filled = 0
    for x in L:                # encode all numbers
        rice_code(f, x, k)
    for i in range(8-filled):  # write the last byte (if necessary pad with 1111...)  
        put_bit(f, 1)
    return f.getvalue()

if __name__ == '__main__':
    print struct.pack('BBB', 0b00010010, 0b00111001, 0b01111111)      #see http://fr.wikipedia.org/wiki/Codage_de_Rice#Exemples
    print compress([1,2,3,10],k = 3)    
导入结构
导入StringIO
def put_位(f,b):
全局buff,填充
buff=buff |(b i)和1)
def压缩(L,k):
f=StringIO.StringIO()
全局buff,填充
buff=0
填充=0
对于L中的x:#对所有数字进行编码
rice_代码(f,x,k)
对于范围内的i(8填充):#写入最后一个字节(如有必要,用1111…)填充)
put_位(f,1)
返回f.getvalue()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
打印结构包('BBB',0b00010010,0B001111001,0b01111111)#参见http://fr.wikipedia.org/wiki/Codage_de_Rice#Exemples
打印压缩([1,2,3,10],k=3)

PS:这个问题是否应该转移到?

在构建压缩结果时,我将使用C风格的缓冲区而不是StringIO,并且我将尝试在编码循环中仅使用C风格的临时性。我还注意到,您可以预先初始化缓冲区,用设置位('1'位)填充,这将加快大商编码值的速度,因为您可以简单地跳过输出缓冲区中的这些位。我重新编写压缩函数时考虑到了这些问题,并测量了结果的速度,我的版本似乎比编码器快十倍多,但生成的代码可读性较差

以下是我的版本:


cimport cpython.string
cimport libc.stdlib
cimport libc.string
import struct

cdef int BUFFER_SIZE = 4096

def compress(L, k):
    result = ''

    cdef unsigned cvalue
    cdef char *position
    cdef int bit, nbit
    cdef unsigned q, r
    cdef unsigned ck = k
    cdef unsigned mask = (1 << ck) - 1

    cdef char *buff = <char *>libc.stdlib.malloc(BUFFER_SIZE)
    if buff is NULL:
        raise MemoryError

    try:
        #  Initialize the buffer space is assumed to contain all set bits
        libc.string.memset(buff, 0xFF, BUFFER_SIZE)

        position = buff
        bit = 7

        for value in L:
            cvalue = value
            q = cvalue >> ck
            r = cvalue & mask

            #  Skip ahead some number of pre-set one bits for the quotient
            position += q / 8
            bit -= q % 8
            if bit < 0:
                bit += 8
                position += 1

                #  If we have gone off the end of the buffer, extract 
                #  the result and reset buffer pointers
                while position - buff >= BUFFER_SIZE:
                    block = cpython.string.PyString_FromStringAndSize(
                        buff, BUFFER_SIZE)
                    result = result + block

                    libc.string.memset(buff, 0xFF, BUFFER_SIZE)
                    position = position - BUFFER_SIZE

            #  Clear the final bit to indicate the end of the quotient
            position[0] = position[0] ^ (1 << bit)
            if bit > 0:
                bit = bit - 1
            else:
                position += 1
                bit = 7

                #  Check for buffer overflow
                if position - buff >= BUFFER_SIZE:
                    block = cpython.string.PyString_FromStringAndSize(
                        buff, BUFFER_SIZE)
                    result = result + block

                    libc.string.memset(buff, 0xFF, BUFFER_SIZE)
                    position = buff

            #  Encode the remainder bits one by one
            for nbit in xrange(k - 1, -1, -1):
                position[0] = (position[0] & ~(1 << bit)) | \
                              (((r >> nbit) & 1) << bit)

                if bit > 0:
                    bit = bit - 1
                else:
                    position += 1
                    bit = 7

                    #  Check for buffer overflow
                    if position - buff >= BUFFER_SIZE:
                        block = cpython.string.PyString_FromStringAndSize(
                            buff, BUFFER_SIZE)
                        result = result + block

                        libc.string.memset(buff, 0xFF, BUFFER_SIZE)
                        position = buff

        #  Advance if we have partially used the last byte
        if bit < 7:
            position = position + 1

        #  Extract the used portion of the buffer
        block = cpython.string.PyString_FromStringAndSize(
            buff, position - buff)
        result = result + block

        return result

    finally:
        libc.stdlib.free(buff)


def test():
    a = struct.pack('BBB', 0b00010010, 0b00111001, 0b01111111)      #see http://fr.wikipedia.org/wiki/Codage_de_Rice#Exemples
    b = compress([1,2,3,10],k = 3)

    assert a == b

cimport cpython.string
cimport libc.stdlib
cimport libc.string
导入结构
cdef int BUFFER_SIZE=4096
def压缩(L,k):
结果=“”
cdef无符号cvalue
cdef字符*位置
cdef int位,nbit
无符号q,r
cdef无符号ck=k
cdef无符号掩码=(1>ck
r=C值和掩码
#提前跳过一些预先设置的商的1位
位置+=q/8
位-=q%8
如果位<0:
位+=8
位置+=1
#如果我们离开了缓冲区的末尾,请提取
#结果和重置缓冲区指针
当位置-buff>=缓冲区大小时:
block=cpython.string.PyString\u FromStringAndSize(
缓冲区(缓冲区大小)
结果=结果+块
libc.string.memset(buff,0xFF,缓冲区大小)
位置=位置-缓冲区大小
#清除最后一位以指示商的结束
位置[0]=位置[0]^(10:
位=位-1
其他:
位置+=1
位=7
#检查缓冲区溢出
如果位置-buff>=缓冲区大小:
block=cpython.string.PyString\u FromStringAndSize(
缓冲区(缓冲区大小)
结果=结果+块
libc.string.memset(buff,0xFF,缓冲区大小)
位置=浅黄色
#对剩余的位逐个进行编码
对于X范围内的nbit(k-1,-1,-1):
位置[0]=(位置[0]&~(1>nbit)和1)0:
位=位-1
其他:
位置+=1
位=7
#检查缓冲区溢出
如果位置-buff>=缓冲区大小:
block=cpython.string.PyString\u FromStringAndSize(
缓冲区(缓冲区大小)
结果=结果+块
libc.string.memset(buff,0xFF,缓冲区大小)
位置=浅黄色
#如果部分使用了最后一个字节,则前进
如果位<7:
位置=位置+1
#提取缓冲区的已用部分
block=cpython.string.PyString\u FromStringAndSize(
buff,位置-buff)
结果=结果+块
返回结果
最后:
libc.stdlib.free(buff)
def test():
a=结构包('BBB',0b00010010,0B001111001,0b01111111)#参见http://fr.wikipedia.org/wiki/Codage_de_Rice#Exemples
b=压缩([1,2,3,10],k=3)
断言a==b

我建议对其进行分析,看看瓶颈在哪里事实上是这样的。@ SurfFaFK你会做什么?你有一个小例子吗?在Python中已经有了一个<代码>配置文件< /C>模块。除了Python Wiki之外,这个Python代码几乎肯定是从这里移植过来的:FWIW,你也可以考虑使用<代码> cpython。此任务的ode>s,基本上是浅包装的
malloc
s。有关一些示例,请参阅。