Высокопроизводительные операции с массивами с помощью Cython | Комплект 2

Опубликовано: 12 Апреля, 2022

Предварительное условие: высокопроизводительные операции с массивами с помощью Cython | Комплект 1

The resulting code in the first part works fast. In this article, we will compare the performance of the code with the clip() function that is present in the NumPy library.

Что касается сюрприза, наша программа работает быстро по сравнению с NumPy, написанным на C.

Code #1 : Comparing the performances.

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

Выход :

Time for NumPy clip program : 8.093049556000551

Time for our program :, 3.760528204000366

Well the codes in the article required Cython typed memoryviews that simplifies the code that operates on arrays. The declaration cpdef clip() declares clip() as both a C-level and Python-level function. This means that the function call is more efficently called by other Cython functions (e.g., if you want to invoke clip() from a different Cython function).

Two decorators are used in the code – @cython.boundscheck(False) and @cython.wraparound(False). Such are the few optional performance optimizations.

@ cython.boundscheck (False): исключает все проверки границ массива и используется, если индексирование не выходит за пределы допустимого диапазона.
@ cython.wraparound (False): исключает обработку отрицательных индексов массива как перенос до конца массива (как в списках Python). Включение этих декораторов может значительно ускорить выполнение кода (почти в 2,5 раза быстрее в этом примере при тестировании).

Code #2 : Variant of the clip() function that uses conditional expressions

# 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 работает более чем на 10% медленнее, чем версия, созданная Cython.

Внимание компьютерщик! Укрепите свои основы с помощью базового курса программирования Python и изучите основы.

Для начала подготовьтесь к собеседованию. Расширьте свои концепции структур данных с помощью курса Python DS. А чтобы начать свое путешествие по машинному обучению, присоединяйтесь к курсу Машинное обучение - базовый уровень.