Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.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_Numpy_Cython - Fatal编程技术网

Python Cython字符串支持

Python Cython字符串支持,python,numpy,cython,Python,Numpy,Cython,我正在尝试优化一些代码。我已经使用Numpy和Numba成功地优化了我的大部分项目,但是还有一些剩余的字符串处理代码无法使用这些工具进行优化。因此,我想尝试使用Cython优化此部分 这里的代码接受一个运行长度编码字符串(一个字母,后面有一个数字表示字母重复了多少次)并将其展开。然后,它使用字典查找将扩展字符串转换为0和1的数组,以将字母与0和1的序列相匹配 是否可以使用Cython优化此代码 import numpy as np import re vector_list = ["A22gA

我正在尝试优化一些代码。我已经使用Numpy和Numba成功地优化了我的大部分项目,但是还有一些剩余的字符串处理代码无法使用这些工具进行优化。因此,我想尝试使用Cython优化此部分

这里的代码接受一个运行长度编码字符串(一个字母,后面有一个数字表示字母重复了多少次)并将其展开。然后,它使用字典查找将扩展字符串转换为0和1的数组,以将字母与0和1的序列相匹配

是否可以使用Cython优化此代码

import numpy as np
import re

vector_list = ["A22gA5BA35QA17gACA3QA7gA9IAAgEIA3wA3gCAAME@EACRHAQAAQBACIRAADQAIA3wAQEE}rm@QfpT}/Mp-.n?",
                "A64IA13CA5RA13wAABA5EAECA5EA4CEgEAABGCAAgAyAABolBCA3WA4GADkBOA?QQgCIECmth.n?"]


_base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@}]^+-*/?,._"
_bin2base64 = {"{:06b}".format(i): base64char for i, base64char in enumerate(_base64chars)}
_base642bin = {v: k for k, v in _bin2base64.items()}

_n_vector_ranks_only = np.arange(1023,-1,-1)


def _decompress_get(data):
    for match in re.finditer(r"(?P<char>.)((?P<count>\d+))?", data):
        if not match.group("count"): yield match.group("char")
        else: yield match.group("char") * int(match.group("count"))


def _n_apply_weights(vector):
    return np.multiply(vector, _n_vector_ranks_only)

def n_decompress(compressed_vector):
    decompressed_b64 = "".join(_decompress_get(compressed_vector))
    vectorized = "".join(_base642bin[c] for c in decompressed_b64)[:-2]
    as_binary = np.fromiter(vectorized, int)
    return as_binary


def test(x, y):
    if len(x) != 1024:
        x = n_decompress(x)
    vector_a = _n_apply_weights(x)
    if len(y) != 1024:
        y = n_decompress(y)
    vector_b = _n_apply_weights(y)
    maxPQ = np.sum(np.maximum(vector_a, vector_b))
    return np.sum(np.minimum(vector_a, vector_b))/maxPQ

v1 = vector_list[0]
v2= vector_list[1]
print(test(v1, v2))
将numpy导入为np
进口稀土
向量_列表=[”A22gA5BA35QA17gACA3QA7gA9IAAgEIA3wA3gCAAME@EACRHAQAAQBACIRAADQAIA3wAQEE}rm@QfpT}/Mp-.n.“,
“A64IA13CA5RA13WAABA5EAECA5EA4CEGEAABGCAAGAYAABOBCA3WA4GADKBOA?QQGCiechm.n?”]
_base64chars=“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@}]^+-*/?,."
_bin2base64={“{:06b}”。格式(i):base64char表示i,base64char表示枚举(_base64chars)}
_base642bin={v:k代表k,v在_bin2base64.items()}
_n_向量_秩仅=np.arange(1023,-1,-1)
def_解压_获取(数据):
对于re.FindItemer(r“(?P.)(?P\d+))”中的匹配,数据:
如果不匹配.group(“count”):则生成匹配.group(“char”)
else:yield match.group(“char”)*int(match.group(“count”))
定义n应用权重(向量):
返回np.multiply(仅向量、向量和秩)
def n_解压缩(压缩向量):
解压缩的\u b64=“”.连接(\u解压缩\u获取(压缩的\u向量))
矢量化的=“”.join(_base642bin[c]表示解压缩的_b64中的c)[:-2]
as_binary=np.fromiter(矢量化,int)
以二进制形式返回
def测试(x,y):
如果len(x)!=1024:
x=n_解压(x)
向量a=\n\u应用\u权重(x)
如果len(y)!=1024:
y=n_解压(y)
向量_b=_n_应用_权重(y)
maxPQ=np.和(np.最大值(向量a,向量b))
返回np.sum(np.minimum(向量a,向量b))/maxPQ
v1=向量_列表[0]
v2=向量_列表[1]
打印(测试(v1、v2))

仅使用Numpy就可以很好地加速问题的第二部分(通过字典查找)。我已经通过索引到Numpy数组来代替字典查找

我在开始时生成Numpy数组。一个诀窍是认识到字母可以用
ord
转换成表示它们的基本数字。对于ASCII字符串,该值始终介于0和127之间:

_base642bin_array = np.zeros((128,),dtype=np.uint8)
for i in range(len(_base64chars)):
    _base642bin_array[ord(_base64chars[i])] = i
我在
n_decompress
函数中使用内置的numpy函数将其转换为1和0

def n_decompress2(compressed_vector):
    # encode is for Python 3: str -> bytes
    decompressed_b64 = "".join(_decompress_get(compressed_vector)).encode()
    # byte string into the underlying numeric data
    decompressed_b64 = np.fromstring(decompressed_b64,dtype=np.uint8)
    # conversion done by numpy indexing rather than dictionary lookup
    vectorized = _base642bin_array[decompressed_b64]
    # convert to a 2D array of 1s and 0s
    as_binary = np.unpackbits(vectorized[:,np.newaxis],axis=1)
    # remove the two digits you don't care about (always 0) from binary array
    as_binary = as_binary[:,2:]
    # reshape to 1D (and chop off two at the end)
    return as_binary.ravel()[:-2]
这使我的速度比你的版本快了2.4倍(请注意,我根本没有改变
\u decompress\u get
,所以这两个计时都包括你的
\u decompress\u get
),只是因为使用了Numpy(没有Cython/Numba,我怀疑它们不会有太大帮助)。我认为主要的优点是,与字典查找相比,索引到带有数字的数组速度更快



\u decompresse\u get
可能可以使用Cython进行改进,但这是一个非常困难的问题…

问题中应包含相关代码(非场外)。代码为862个字符,太长了,我已将代码编辑到问题中。问这个问题的主要原因是,我们希望将来的问题对其他人有用,而且链接可以很容易地删除好的,所以我用代码删除我的评论,谢谢。我已经尝试过让问题更清楚一点。。。检查编辑,看看你是否同意。我尝试了代码,测试时有1000000个向量,从372秒到209秒,非常令人印象深刻,谢谢。我要求cython改进可能只涉及数字的测试部分,所以我写了这样的东西:
cdef np.int\t[:]\u n\u应用权重(np.int\t[:]向量):返回np.multiply(向量,仅向量秩)
cdef np.int\t[:]n\u解压缩(压缩向量):\cdef char*decompressed\u b64,矢量化的解压缩的矢量化的=“”。join(_decompression_get(compressed_vector))矢量化的=“”。join(_base642bin[c]表示解压缩的b64中的c)[:-2]cdef np.int_t[:]as_binary=np。fromiter(矢量化的,int)返回为_binary
cdef double cy_test(x=vector_list[0],y=vector_list[1]):cdef np.int_t[:]ix,iy,vector_a,如果len(x)!=1024:ix=n_解压缩(x)向量_a=_n_应用_权重(ix)(如果len(y)!=1024:iy=n_decompress(y)vector_b=\u n_apply_weights(iy)cdef double maxPQ=np.sum(np.maximum(vector_a,vector_b))返回np.sum(np.minimum(vector_a,vector_b))/maxPQ
,但它似乎没有帮助,它比numpy花费更多的时间。我在这里读到:这不是Cython用于优化的那种代码。您所做的只是调用Numpy函数,这些函数已经用C编写,所以您所添加的只是一些不必要的Cython类型检查。此外,您已将
n\u decompress
变为内存管理灾难(您的
char*
s仅在它们指向的变量处于活动状态时有效,但这是一个短暂的临时变量)