gpt4 book ai didi

python - cython cdef C 类方法 : how to call it from another cython cdef class without python overhead?

转载 作者:太空宇宙 更新时间:2023-11-04 06:10:48 26 4
gpt4 key购买 nike

我正在尝试在 cython 中实现通用排序算法。因此,我创建了以下模块,它在 sorter_t 类中实现了 Heapsort 算法:

# file general_sort_c.pyx

from libc.stdint cimport int32_t
cdef bint bint_true = 1
cdef bint bint_false = 0

cdef class sorter_t:

cdef object sortable_object

def __init__(self,sortable_object):
self.sortable_object = sortable_object

cpdef sort_c(self):

"""
https://en.wikipedia.org/wiki/Heapsort

"""

cdef int32_t end
cdef int32_t count = self.sortable_object.num_elements_int32

self.heapify_c(count)

end = count-1
while end > 0:
self.sortable_object.swap_c(0,end)
end = end - 1
self.siftDown_c(0,end)

cdef heapify_c(self,int32_t count):

cdef int32_t start = (count - 2)/2

while start >= 0:
self.siftDown_c(start, count-1)
start -= 1

cdef siftDown_c(self,int32_t start, int32_t end):

cdef int32_t root = start
cdef int32_t swap
cdef int32_t child

while root * 2 + 1 <= end:

child = root * 2 + 1
swap = root

# if "swap" < "child" then ...
if self.sortable_object.lt_c(swap,child) == 1:
swap = child

if child+1 <= end and self.sortable_object.lt_c(swap,child+1) == 1:
swap = child + 1

if swap != root:
self.sortable_object.swap_c(root,swap)
root = swap
else:
return

当你定义一个 sorter_t 类型的对象时,你必须提供一个 sortable_object ,它有自己特定的 cdef 函数 lt_c 实现(对于比较一个元素是否小于另一个元素)和 swap_c(用于交换元素)。

例如,以下代码将从列表定义和创建一个sortable_object,并将使用该sortable_object 测试“sorter_t”的实现。

import numpy
cimport numpy
from libc.stdint cimport int32_t
import general_sort_c

cdef class sortable_t:

cdef public int32_t num_elements_int32
cdef int32_t [:] mv_lista

def __init__(self,int32_t [:] mv_lista):
self.num_elements_int32 = mv_lista.shape[0]
self.mv_lista = mv_lista

cdef public bint lt_c(self, int32_t left, int32_t right):
if self.mv_lista[left] < self.mv_lista[right]:
return 1 # True
else:
return 0 # False

cdef public bint gt_c(self, int32_t left, int32_t right):
if self.mv_lista[left] > self.mv_lista[right]:
return 1 # True
else:
return 0 # False

cdef public swap_c(self, int32_t left, int32_t right):
cdef int32_t tmp
tmp = self.mv_lista[right]
self.mv_lista[right] = self.mv_lista[left]
self.mv_lista[left] = tmp

def probar():

lista = numpy.array([3,4,1,7],dtype=numpy.int32)
cdef int32_t [:] mv_lista = lista

cdef sortable = sortable_t(mv_lista)
cdef sorter = general_sort_c.sorter_t(sortable)
sorter.sort_increasing_c()
print list(lista)

编译完 .pyx 文件并在 IPython 控制台中运行以下命令后,出现以下错误:

In [1]: import test_general_sort_c as tgs

In [2]: tgs.probar()

...

general_sort_c.sorter_t.siftDown_increasing_c (general_sort_c.c:1452)()
132
133 #if mv_tnet_time[swap] < mv_tnet_time[child]:

--> 134 if self.sortable_object.lt_c(swap,child) == bint_true:
135 swap = child
136

AttributeError: 'test_general_sort_c.sortable_t' object has no attribute 'lt_c'

因此,问题是函数 lt_c 的实现从模块 general_sort_c.pyx 中的代码中看不到。如果我使用 cpdef 而不是 cdef 定义函数 lt_c 它会工作,但是你有很多 Python 开销。如何以 cdef(“纯 C”)方式调用此函数?

最佳答案

不幸的是,我不确定如何让它与融合类型一起工作,但剩下的很简单:

test_general_sort_c.pyx 需要免费的 test_general_sort_c.pxd:

from libc.stdint cimport int32_t

cdef class sortable_t:
cdef public int32_t num_elements_int32
cdef int32_t [:] mv_lista
cdef public bint lt_c(self, int32_t left, int32_t right)
cdef public bint gt_c(self, int32_t left, int32_t right)
cdef public swap_c(self, int32_t left, int32_t right)

general_sort_c.pyx 必须 cimport test_general_sort_c 并输入它的 self.sortable_object 成为一个 test_general_sort_c.sortable_t.

当然,如果您可以拥有多种受支持的类型,那就更好了。不过,我不确定你现在会怎么做。


此外,内置的 TrueFalse 可以自己正常工作。

如果你更信任 Cython,你会发现你可以写

cdef public bint lt_c(self, int32_t left, int32_t right):
return self.mv_lista[left] < self.mv_lista[right]

cdef public bint gt_c(self, int32_t left, int32_t right):
return self.mv_lista[left] > self.mv_lista[right]

cdef public swap_c(self, int32_t left, int32_t right):
self.mv_lista[right], self.mv_lista[left] = self.mv_lista[left], self.mv_lista[right]

就好了。 :)

关于python - cython cdef C 类方法 : how to call it from another cython cdef class without python overhead?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18850671/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com