python - Cythonizing 使用 numpy 的函数
问题描述
我正在尝试对以下代码进行cythonize:
def my_func(vector_b):
vector_b = np.unpackbits(np.frombuffer(vector_b, dtype=np.uint8))
vector_b = (vector_b * _n_vector_ranks_only)
min_ab = np.sum(np.minimum(vector_a, vector_b))
max_ab = np.sum(np.maximum(vector_a, vector_b))
return min_ab / max_ab
_n_vector_ranks_only = np.arange(1023, -1, -1, dtype=np.uint16)
# vector_a data type is same of vector_b, is not contained in db, it is passed manually
vector_a = np.frombuffer(vector_a, dtype=np.uint8)
vector_a = (vector_a * _n_vector_ranks_only)
#fetch all vectors from DB
df = dd.read_sql_table('mydb', 'postgresql://user:passwordg@localhost/table1', npartitions=16, index_col='id', columns=['data'])
res = df.map_partitions(lambda df: df.apply( lambda x: my_func(x['data']), axis=1), meta=('result', 'double')).compute(scheduler='processes')
#data is a binary array saved with numpy packbits
目前我在这一点上:
from ruzi_cython import ruzicka
def my_func(vector_b):
vector_b = np.unpackbits(np.frombuffer(vector_b, dtype=np.uint8))
vector_b = (vector_b * _n_vector_ranks_only)
#min_ab = np.sum(np.minimum(vector_a, vector_b))
#max_ab = np.sum(np.maximum(vector_a, vector_b))
#return min_ab / max_ab
return ruzicka.run_old(vector_a, vector_b)
其中 ruzicka.pyx 是这样的:
# cython: profile=True
import numpy as np
cimport numpy as np
cimport cython
ctypedef np.uint16_t data_type_t
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.overflowcheck(False)
@cython.initializedcheck(False)
cdef double ruzicka_old(data_type_t[:] a, data_type_t[:] b):
cdef int i
cdef float max_ab = 0
cdef float min_ab = 0
for i in range(1024):
if a[i] > b[i]:
max_ab += a[i]
min_ab += b[i]
else:
max_ab += b[i]
min_ab += a[i]
return min_ab / max_ab
def run_old(a, b):
return ruzicka_old(a, b)
在那里我获得了很多表演。在我进行两个数组相乘的第一部分,我仍然无法以良好的结果进行 cythonize。
这就是我做乘法的方式:
cdef double ruzicka(data_type_16[:] a, data_type_8[:] b):
cdef int i
cdef float max_ab = 0
cdef float min_ab = 0
cdef data_type_16 tmp = 0
for i in range(1024):
tmp = b[i] * (1023-i)
if a[i] > tmp:
max_ab += a[i]
min_ab += tmp
else:
max_ab += tmp
min_ab += a[i]
return min_ab / max_ab
解决方案
看起来您正在努力获取数组的第 n 位(基本上是在做什么np.unpackbits
)。
第 n 位包含在n//8
字节中(我使用的是//
除法和向下取整运算符)。您可以访问一个字节中的单个位,执行“按位与”( &
) 与1<<m
(一个位移位m
)。这会给你 number 2**(m-1)
,你真的只关心它是否为 0 。
所以假设这vector_b
是一个np.int8_t
内存视图,你可以这样做:
byte_idx = n//8
bit_idx = n%8 # remainder operator
bitmask = 1<<bit_idx
bit_is_true = 1 if (vector_b[byte_idx]&bitmask) else 0
你需要把它放在一个循环和cdef
变量的类型中。
推荐阅读
- javascript - 仅显示列表中的 7 个列表项,在“下一个”上单击隐藏当前 7 显示下一个 7,与“上一个”单击相同
- android - 赋值不是表达式,在这种情况下只允许使用表达式 - Kotlin
- php - How to Limit Excerpt Length in $category->description in archive-products.php WordPress?
- c# - 如何将多个 OData 微服务缝合(合并、连接……)在一起
- exchange-server - 自定义事件 ID
- arrays - 可被给定小素数整除的大小为 3 的子集的数量
- swift - 如何处理具有相同名称的快速类?
- java - @Qualifier 可以“看到”一连串的依赖关系吗?
- javascript - Javascript - 从外部脚本中删除所有副作用
- c# - ASP .NET MVC Windows 授权不起作用