标签: cython

Cython快速将二进制字符串转换为int数组

我有一个大型二进制数据文件,我想将其加载到 C 数组中以便快速访问。数据文件仅包含 4 字节整数序列。

我通过 pkgutil.get_data 函数获取数据,该函数返回一个二进制字符串。以下代码有效:

import pkgutil
import struct

cdef int data[32487834]

def load_data():
    global data
    py_data = pkgutil.get_data('my_module', 'my_data')
    for i in range(32487834):
        data[i] = <int>struct.unpack('i', py_data[4*i:4*(i+1)])[0]
    return 0

load_data()
Run Code Online (Sandbox Code Playgroud)

问题是这段代码非常慢。读取整个数据文件可能需要 7 或 8 秒。将文件直接读入 C 中的数组只需 1-2 秒,但我想使用 pkgutil.get_data 以便我的模块无论安装在何处都可以可靠地找到数据。

所以,我的问题是:最好的方法是什么?有没有办法直接将数据转换为整数数组,而不需要对 struct.unpack 进行所有调用?而且,作为第二个问题,有没有一种方法可以简单地获取指向数据的指针,以避免不必要地复制 120MB 的数据?

或者,有没有办法让 pkgutil 返回数据的文件路径而不是数据本身(在这种情况下,我可以使用 C 文件 IO 来快速读取文件。

编辑:

仅供记录,这是最终使用的代码(基于 Veedrac 的答案):

import pkgutil

from cpython cimport array
import array

cdef int[:] data

cdef void load_data():
    global data
    py_data = pkgutil.get_data('my_module', …
Run Code Online (Sandbox Code Playgroud)

python arrays distutils cython

0
推荐指数
1
解决办法
2390
查看次数

在Cython生成的C代码中优化掉PyFloat_FromDouble,Pyx_GetItemInt和PyObject_RichCompare

我试图在Cython中为Python编写一个运行长度编码算术库.下面你会看到声明和算法热循环的重要部分是如何看的.它有两个地方有很多和中等的Python交互,第73-74行和第77行.为重度Python交互部分生成的C代码最后显示在一张图片中.我只会询问如何在这里解决73-74,因为我认为77的修复程序是相似的.

正如您所看到的,在生成的C代码中有1)很多类型转换,2)它使用richcompare和3)getitemint.我不明白为什么:1)类型应该是相同的,2)比较应该可以在C级别,因为他们只是比较相同类型的数字和3)getitem应该是多余的,因为你只是查找一个C数组中的索引.

如何解决这个问题以优化我的代码?numpy数组声明创建Python对象的问题是否需要以某种方式指向它们?

在此输入图像描述

在这里,您可以看到为我的热循环中的两个黑暗和淡黄色位置生成的C代码Cython:

在此输入图像描述

python types numpy cython

0
推荐指数
1
解决办法
198
查看次数

Cythonize python3 代码而不使用类型提示/注释

是否可以在不使用类型提示/注释的情况下对 python3 代码进行 cythonize?

我正在尝试对一个小型 python3 代码库进行 cythonize,但我遇到了一些问题,因为代码中的某些类型提示不正确,这在尝试运行 cythonized 代码时会导致问题。

这是一个简化的例子,

a.py

def test_func(arg1) -> str:
    return {"hello": "world"}
Run Code Online (Sandbox Code Playgroud)

运行 cythonize 后尝试运行代码时出现错误

TypeError: Expected unicode, got dict
Run Code Online (Sandbox Code Playgroud)

如果我删除注释,一切都会正常-> str。那么,有没有办法告诉 cython 忽略所有注释?

我知道解决此问题的正确方法是修复类型提示,但我在修复注释时试图找到替代解决方案。

这是我的setup.py

#cython: language_level=3
#cython: annotation_typing=False
from setuptools import setup
from setuptools.extension import Extension

from Cython.Build import cythonize
from Cython.Distutils import build_ext

setup(
    name="lib",
    ext_modules=cythonize(
        [
           Extension("pkg1.*", ["pkg1/*.py"], include_dirs = ["."], extra_compile_args = ['-O3']),
        ],
        build_dir="build",
        compiler_directives=dict(
        always_allow_keywords=True,
        language_level=3)),
    cmdclass=dict(
        build_ext=build_ext
    ),
    packages=["pkg1"]
)
Run Code Online (Sandbox Code Playgroud)

谢谢。

python cython python-3.x cythonize

0
推荐指数
1
解决办法
1018
查看次数

在 Python 中使用嵌套循环重写 MATLAB 代码并快速执行

这是一个嵌套循环,其中内部索引取决于外部索引,具有以下参数:

f = rand(1,70299)
nech=24*30*24
N=length(f);
xh=(1:nech)/24;
Run Code Online (Sandbox Code Playgroud)

在 MATLAB 中:

sf2(1:nech)=0.;
sf2vel(1:nech)=0.;
count(1:nech)=0.;

for i=1:nech
    for j=1:N-i-1
        sf2(i)=sf2(i)+(f(j+i)-f(j))^2;
        count(i)=count(i)+1; 
    end
    sf2(i)=sf2(i)/count(i);
end
Run Code Online (Sandbox Code Playgroud)

在Python中:

def structFunPython(f,N,nech):
    sf2 = np.zeros(N)
    count = np.zeros(N)
    for i in range(nech):
        indN = np.arange(1,N-i-1)
        for j in indN:
            sf2[i] += np.power((f[i+j]-f[j]),2)
            count[i] += 1
        sf2[i] = sf2[i]/count[i]
    return sf2
Run Code Online (Sandbox Code Playgroud)

与赛通:

import cython
cimport numpy as np
import numpy as np
def structFun(np.ndarray f,N,nech):
    cdef np.ndarray sf2 = np.zeros(N), count = np.zeros(N),
    for i in range(nech):
        indN …
Run Code Online (Sandbox Code Playgroud)

python matlab numpy cython nested-loops

0
推荐指数
3
解决办法
411
查看次数

在 Cython 中循环二维数组的最快方法

我正在尝试在 Cython 中循环 2 个 2d 数组。数组具有以下形状: ranges_1是 的 6000x3 数组int64,而ranges_2是 的 2000x2 数组int64。这个迭代需要执行10000次左右。这意味着嵌套 for 循环内的计算总数约为 2000x6000x10000 = 1200 亿次。

这是我用来生成“虚拟”数据的代码:

import numpy as np
ranges_1 = np.stack([np.random.randint(0, 10_000, 6_000), np.random.randint(0, 10_000, 6_000), np.arange(0, 6_000)], axis=1)
ranges_2 = np.stack([np.random.randint(0, 10_000, 2_000), np.random.randint(0, 10_000, 2_000)], axis=1)
Run Code Online (Sandbox Code Playgroud)

这给出了 2 个像这样的数组:

array([[6131, 1478,    0],
       [9317, 7263,    1],
       [7938, 6249,    2],
       ...,
       [5153,  426, 5997],
       [9164, 9211, 5998],
       [1695, 1792, 5999]])
Run Code Online (Sandbox Code Playgroud)

和:

array([[ 433,  558],
       [3420, 2494], …
Run Code Online (Sandbox Code Playgroud)

python optimization performance cython

0
推荐指数
1
解决办法
320
查看次数

接收全局变量(Cython)

我在 jupyter 笔记本中使用 Cython。

据我所知,Cython 编译 def 函数。

但是当我想用全局变量调用函数时,它看不到它。

有没有什么方法可以用变量调用函数?

one1 = 1
%%cython
cimport numpy as np
cdef nump(number1):
    return number1 + 1
nump(one1)
Run Code Online (Sandbox Code Playgroud)

****这是示例代码,向版主展示

python cython

-3
推荐指数
2
解决办法
1276
查看次数