📌  相关文章
📜  Cython 的高性能阵列操作 |设置 2

📅  最后修改于: 2022-05-13 01:55:44.437000             🧑  作者: Mango

Cython 的高性能阵列操作 |设置 2

先决条件:使用 Cython 进行高性能阵列操作 |设置 1
第一部分中生成的代码运行速度很快。在本文中,我们将比较代码的性能与 NumPy 库中的clip()函数。
令人惊讶的是,与用 C 编写的 NumPy 相比,我们的程序运行得更快。
代码#1:比较性能。

Python3
a = timeit('numpy.clip(arr2, -5, 5, arr3)',
       'from __main__ import b, c, numpy', number = 1000)
 
print ("\nTime for NumPy clip program : ", a)
 
b = timeit('sample.clip(arr2, -5, 5, arr3)',
           'from __main__ import b, c, sample', number = 1000)
 
print ("\nTime for our program : ", b)


Python3
# decorators
@cython.boundscheck(False)
@cython.wraparound(False)
 
cpdef clip(double[:] a, double min, double max, double[:] out):
     
    if min > max:
        raise ValueError("min must be <= max")
     
    if a.shape[0] != out.shape[0]:
        raise ValueError
        ("input and output arrays must be the same size")
     
    for i in range(a.shape[0]):
        out[i] = (a[i]
        if a[i] < max else max)
        if a[i] > min else min


输出 :

Time for NumPy clip program : 8.093049556000551

Time for our program :, 3.760528204000366

那么文章中的代码需要Cython 类型的 memoryviews来简化对数组进行操作的代码。声明cpdef clip() 将 clip()声明为 C 级和 Python 级函数。这意味着函数调用由其他 Cython 函数更有效地调用(例如,如果您想从不同的 Cython函数调用 clip() )。
代码中使用了两个装饰器—— @cython.boundscheck(False)@cython.wraparound(False) 。这是少数可选的性能优化。
@cython.boundscheck(False) :消除所有数组边界检查,如果索引不会超出范围,则使用。
@cython.wraparound(False) :消除了将负数组索引处理为环绕到数组末尾的处理(就像Python列表一样)。包含这些装饰器可以使代码运行得更快(在这个例子中测试时几乎快 2.5 倍)。
代码 #2:使用条件表达式的 clip()函数的变体

Python3

# decorators
@cython.boundscheck(False)
@cython.wraparound(False)
 
cpdef clip(double[:] a, double min, double max, double[:] out):
     
    if min > max:
        raise ValueError("min must be <= max")
     
    if a.shape[0] != out.shape[0]:
        raise ValueError
        ("input and output arrays must be the same size")
     
    for i in range(a.shape[0]):
        out[i] = (a[i]
        if a[i] < max else max)
        if a[i] > min else min

经过测试,这个版本的代码运行速度提高了 50% 以上。但是这段代码如何与手写的 C 版本叠加。经过实验,可以测试到手工制作的 C 扩展运行速度比 Cython 创建的版本慢 10% 以上。