Numpy cython memoryview不比ndarray快

Numpy cython memoryview不比ndarray快,numpy,cython,memoryview,Numpy,Cython,Memoryview,我有一个用常规numpy-ndarray编写的函数,还有一个用键入的memoryview编写的函数。然而,我无法让memoryview版本比常规版本运行得更快(不像许多博客,例如) 如果您有任何关于提高memoryview代码速度的建议或建议,我们将不胜感激。。。或如果有人能指出memoryview版本没有比常规numpy版本快多少的明显原因 在下面的代码中有两个函数,它们都接受两个向量bi和xi,并返回一个矩阵。第一个函数shrink\u correl是常规的numpy版本,第二个函数shri

我有一个用常规
numpy-ndarray
编写的函数,还有一个用
键入的memoryview
编写的函数。然而,我无法让
memoryview
版本比常规版本运行得更快(不像许多博客,例如)

如果您有任何关于提高memoryview代码速度的建议或建议,我们将不胜感激。。。或如果有人能指出memoryview版本没有比常规numpy版本快多少的明显原因

在下面的代码中有两个函数,它们都接受两个向量
bi
xi
,并返回一个矩阵。第一个函数
shrink\u correl
是常规的numpy版本,第二个函数
shrink\u correl2
是memoryview替代(让文件为
sh\u cor.pyx

这是使用以下
setup.py
代码编译的

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy as np
import os

ext_modules = [Extension('sh_cor', ['sh_cor.pyx'], include_dirs=[np.get_include(),
                                                                 os.path.join(np.get_include(), 'numpy')],
                         define_macros=[('NPY_NO_DEPRECATED_API', None)],
                         extra_compile_args=['-O3', '-march=native', '-ffast-math', '-flto'],
                         libraries=['m']
                         )]

setup(
    name="Sh Cor",
    cmdclass={'build_ext': build_ext},
    ext_modules=ext_modules
)
用于测试速度的代码为

import numpy as np
import sh_cor  # this the library created by the setup.py file
import time

b = np.random.random(400)
b = b/np.sum(b)

x = np.random.random(400)-0.5

n = 10 

t0 = time.time()
for i in range(n):
    v1 = sh_cor.shrink_correl(b, x)
t1 = time.time()
print((t1-t0)/n)

t0 = time.time()
for i in range(n):
    v2 = sh_cor.shrink_correl2(b, x)
t1 = time.time()
print((t1-t0)/n)
我的电脑上的输出为:

0.7070999860763549   # regular numpy
0.6726999998092651   # memoryview

使用memoryview(在上面的代码中)只能给我5%的速度提升(不同于博客中的巨大速度提升)

@uday给我大约一周的时间,因为我没有电脑,但这里有一些地方可以让你加速开始:1)不要使用
np连接gil。transpose
在任何循环之前创建一个与你想要转置的内容相同的memoryview(即,将变量
f
声明为不需要gil的memoryview,只需在该
f\u t
上创建一个视图,即
cdef double[:,::1]f\u t=np.转置(f)
或只是
=f.t

2) 这一步有点棘手,因为您需要一个C/C++风格的包装器版本的
np.dot
(因此,在本例中,确保调用
dgemm
函数是
,上面加上nogil:
,并缩进下一行的函数,以释放gil,缩进4个空格)(尽管您必须保存include
f2pyptr.h
文件并将其放在项目正在构建的位置;但我也怀疑您应该将
cimport numpy添加为np
);如果没有,并且它需要mods,你可以像我在这里的另一篇文章中所做的那样看到:那么你需要在顶部添加cython.parallel cimport prange的
,并将所有循环从
range
更改为
prange
,确保所有
prange
部分都是
nogil
,所有变量都是
cdef
decla红色。此外,您必须在编译器参数中向setup.py添加
-openmp
,以及指向其include libs的链接。如果需要澄清,请询问更多问题。这并不像应该的那样简单,但需要一点指导就变得非常简单了。基本上,一旦您的
setup.py
被修改为In包括一切它将继续工作


(三)尽管可能是最容易修复的-摆脱该列表。如果需要文本和数据,可以将其设置为numpy数组或pandas数据帧。每当我使用列表进行数据处理时,速度都令人难以置信。

有什么不同?只是函数参数的规格说明?当我看到大量代码而不进行解释时,我的眼睛都会发呆。是的,差不多。大部分功能都是循环的。我的印象是,当你将
记忆视图的使用集中在低级操作时,你会从中获得最大的好处。但我还没有对你的代码进行足够的研究,以了解这是否是你的情况。此外,你链接到的博客所谈论的优势是在你创建切片时使用的,例如
double[:]x=some_2d_array[:,0]
,这显然在
ndarrays
中效率低下。如果您不这样做,您可能不会获得这种好处。直接访问元素可能非常类似(请查看此处的C代码以进行检查)。我看到两者之间的一个区别是,在第一个函数输入中,
ndarray
以及
s
g
c-连续的
,而在第二个函数中则不是。请使用
double[::1]
而不是
double[:]
。除此之外,您的大多数操作都需要相同的numpy C-API,因此您肯定不会看到任何加速。如果您让cython吐出html文件(
cython-a
),您将基本上看到类似的C代码。
0.7070999860763549   # regular numpy
0.6726999998092651   # memoryview