Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/336.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 实现Numba';s与Cython的演出_Python_Performance_X86_Cython_Numba - Fatal编程技术网

Python 实现Numba';s与Cython的演出

Python 实现Numba';s与Cython的演出,python,performance,x86,cython,numba,Python,Performance,X86,Cython,Numba,在使用Cython时,我通常能够与Numba的性能相匹配。然而,在这个例子中,我没有做到这一点-Numba大约比我的Cython版本快4倍 这里是Cython版本: %%cython -c=-march=native -c=-O3 cimport numpy as np import numpy as np cimport cython @cython.boundscheck(False) @cython.wraparound(False) def cy_where(double[::1] d

在使用Cython时,我通常能够与Numba的性能相匹配。然而,在这个例子中,我没有做到这一点-Numba大约比我的Cython版本快4倍

这里是Cython版本:

%%cython -c=-march=native -c=-O3
cimport numpy as np
import numpy as np
cimport cython

@cython.boundscheck(False)
@cython.wraparound(False)
def cy_where(double[::1] df):
    cdef int i
    cdef int n = len(df)
    cdef np.ndarray[dtype=double] output = np.empty(n, dtype=np.float64)
    for i in range(n):
        if df[i]>0.5:
            output[i] = 2.0*df[i]
        else:
            output[i] = df[i]
    return output 
这是Numba的版本:

import numba as nb
@nb.njit
def nb_where(df):
    n = len(df)
    output = np.empty(n, dtype=np.float64)
    for i in range(n):
        if df[i]>0.5:
            output[i] = 2.0*df[i]
        else:
            output[i] = df[i]
    return output

测试时,Cython版本与NUMPY的<>代码> ,但明显低于NUBA:

#Python3.6 + Cython 0.28.3 + gcc-7.2
import numpy
np.random.seed(0)
n = 10000000
data = np.random.random(n)

assert (cy_where(data)==nb_where(data)).all()
assert (np.where(data>0.5,2*data, data)==nb_where(data)).all()

%timeit cy_where(data)       # 179ms
%timeit nb_where(data)       # 49ms (!!)
%timeit np.where(data>0.5,2*data, data)  # 278 ms
Numba表现出色的原因是什么?在使用Cython时,如何与之匹配


正如@max9111所建议的,通过使用连续内存视图来消除步幅,这并不能显著提高性能:

@cython.boundscheck(False)
@cython.wraparound(False)
def cy_where_cont(double[::1] df):
    cdef int i
    cdef int n = len(df)
    cdef np.ndarray[dtype=double] output = np.empty(n, dtype=np.float64)
    cdef double[::1] view = output  # view as continuous!
    for i in range(n):
        if df[i]>0.5:
            view[i] = 2.0*df[i]
        else:
            view[i] = df[i]
    return output 

%timeit cy_where_cont(data)   #  165 ms

这似乎完全是由LLVM能够进行的优化驱动的。如果我用叮当声编译cython示例,两个示例之间的性能是相同的。值得一提的是,windows上的MSVC显示出与numba类似的性能差异

$ CC=clang ipython
<... setup code>

In [7]: %timeit cy_where(data)       # 179ms
   ...: %timeit nb_where(data)       # 49ms (!!) 

30.8 ms ± 309 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
30.2 ms ± 498 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
$CC=clangipython
在[7]:%timeit cy_其中(数据)#179ms
…:%timeit nb_其中(数据)#49ms(!!)
每个回路30.8 ms±309µs(7次运行的平均值±标准偏差,每个10个回路)
每个回路30.2 ms±498µs(7次运行的平均值±标准偏差,每个10个回路)

有趣的是,使用clang作为后端编译原始Numpy代码,可以获得与Numba版本相同的性能

import numpy as np
#pythran export work(float64[])

def work(df):
    return np.where(data>0.5,2*data, data)
编撰

CXX=clang++ CC=clang pythran pythran_work.py -O3 -march=native
基准会议:

import numpy as np
np.random.seed(0)
n = 10000000
data = np.random.random(n)
import numba_work, pythran_work

%timeit numba_work.work(data)
12.7 ms ± 20 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit pythran_work.work(data)
12.7 ms ± 32.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

这是否提高了性能?看起来像是
cdef np.ndarray[dtype=double]output=np.empty(n,dtype=np.float64)
会导致随后的内存访问速度加快,这通常会阻止SIMD矢量化。(我在使用-a标志生成的html中查找了它,但目前没有可用的gcc。)@max9111如果SIMD矢量化是加速的原因,那么可能应该按照您的建议使用连续内存视图。在本例中,它没有太大变化(请参见我的编辑)。也许这是gcc遗漏的优化?在godbolt中大致相当-看起来clang做了很多“更多”-其中一些只是循环展开,但它的整体矢量化策略也不同。你使用哪个clang版本?这是ubuntu 18.04上的clang 6.0,我印象深刻,更新的clang版本即使在没有人告诉它数据是连续的(较旧的clang版本(3.8)无法做到)时也能获得性能。我不明白为什么gcc不能匹配clang的性能-用纯C编码我看不出有多大区别。但即使在Cython中使用C-code-vebatim,gcc和clang之间也存在巨大的差异。您认为这是因为pythran还是clang与gcc的关系?