Я новичок в Cython.Я пытаюсь ускорить функцию, которая вызывается много раз, и значительное увеличение скорости было бы чрезвычайно полезным.
Моя оригинальная версия этой функции интенсивно использует трансляцию NumPy для больших многомерных массивов.При попытке Cythonize функции я сначала попытался преобразовать эти массивы в представления памяти Cython.Однако затем я столкнулся с ошибками компиляции, поскольку функция выполняет арифметику с этими массивами, и с тех пор я узнал, что это не поддерживается представлениями памяти.
Таким образом, я изменил свой Cythonized код, чтобы объявить массивыкак NumPy ndarrays, а не воспоминания.Функция Cythonized теперь работает, но не дает какой-либо заметной разницы в скорости по сравнению с исходной чистой версией Python / NumPy.
Поэтому я мог бы теперь либо: a.) Принять, что этот код не поддаетсяCythonized и искать в другом месте способ увеличения скорости, или б.) Вернитесь к обработке больших массивов как к просмотрам памяти и каким-то образом преодолеть арифметику, которая должна быть выполнена.
Для продолжения с опцией b.)Я хочу обратиться к арифметике в цикле for этой функции.Я мог бы потенциально написать дополнительные функции Cython, которые выполняют умножение и сложение массива поэлементно, что, как я понимаю, позволило бы мне использовать представления памяти.Однако, учитывая сложную трансляцию NumPy этого кода, я ожидаю, что это может потребовать значительных усилий (и я не обязательно знаю, как начать ...).Кроме того, я не уверен, принесут ли эти усилия свои плоды, учитывая, что выполнение действий по элементам (по общему признанию в C) на самом деле не может быть быстрее, чем операции широковещательной NumPy.
Я быОчень приветствую любые советы или поддержку.Спасибо.
from numpy import pi, exp, sin, cos
import numpy as np
cimport numpy as np
cimport cython
cdef np.ndarray[np.double_t, ndim=3] foo(bar, double dt, f, xi):
cdef int nt, nh, nj
cdef Py_ssize_t t
nt = bar.shape[0]
nh = bar.shape[1]
if len(bar.shape) < 3:
bar = bar[:, np.newaxis, :]
cdef np.ndarray[np.double_t, ndim=3] bar_c = bar
nj = len(f)
k = (2 * pi * f) ** 2
wn = k ** 0.5
wd = (wn * (1 - xi ** 2) ** 0.5)
cdef np.ndarray[np.double_t, ndim=3] u = np.zeros((nt, nj, nh))
cdef np.ndarray[np.double_t, ndim=3] v = np.zeros((nt, nj, nh))
C1 = exp(-xi * wn * dt)
C2 = sin(wd * dt)
C3 = cos(wd * dt)
cdef np.ndarray[np.double_t, ndim=2] A11 = C1 * (C3 + (xi / (1 - xi ** 2) ** 0.5) * C2)
cdef np.ndarray[np.double_t, ndim=2] A12 = (C1 / wd) * C2
cdef np.ndarray[np.double_t, ndim=2] A21 = (-wn / (1 - xi ** 2) ** 0.5) * C1 * C2
cdef np.ndarray[np.double_t, ndim=2] A22 = C1 * (C3 - (xi / (1 - xi ** 2) ** 0.5) * C2)
cdef np.ndarray[np.double_t, ndim=2] B11 = C1 * (
(((2 * xi ** 2 - 1) / (dt * wn ** 2)) + xi / wn) * C2 / wd
+ ((2 * xi / (dt * wn ** 3)) + (1 / wn ** 2)) * C3
) - 2 * xi / (dt * wn ** 3)
cdef np.ndarray[np.double_t, ndim=2] B12 = (
-C1
* (
((2 * xi ** 2 - 1) / (dt * wn ** 2)) * C2 / wd
+ ((2 * xi) / (dt * wn ** 3)) * C3
)
- (1 / wn ** 2)
+ 2 * xi / (dt * wn ** 3)
)
cdef np.ndarray[np.double_t, ndim=2] B21 = -A12 - ((A11 - 1) / (dt * wn ** 2))
cdef np.ndarray[np.double_t, ndim=2] B22 = -B21 - A12
for t in range(0, nt - 1):
u[t + 1, :, :] = (
A11 * u[t, :, :]
+ A12 * v[t, :, :]
+ B11 * bar_c[t, :, :]
+ B12 * bar_c[t + 1, :, :]
)
v[t + 1, :, :] = (
A21 * u[t, :, :]
+ A22 * v[t, :, :]
+ B21 * bar_c[t, :, :]
+ B22 * bar_c[t + 1, :, :]
)
cdef np.ndarray[np.double_t, ndim=3] out = -2 * xi * wn * v - (wn ** 2) * u - bar_c
return out
Извинения за то, что не уменьшили размер кода.Учитывая характер запроса, мне трудно найти минимальный воспроизводимый пример.