Я хочу использовать типизированное представление памяти для оптимизации функции, но не знаю, какой тип аргумента. Это может быть массив numpy или даже скаляр. Как мне тогда использовать типизированную память?
Используйте Typed memoryview в cython, если размеры неизвестны
Ответы (1)
Проблема такого рода проблем заключается в том, что Python использует динамическую типизацию, поэтому вы всегда будете терять скорость при выборе пути кода. Однако, в принципе, вы можете сделать отдельные пути кода довольно быстрыми. Подход, который может дать вам хорошие результаты, будет:
- определить функцию «реализации», которая работает с одномерным представлением памяти.
- Define a wrapper function that operates on any python object.
- If it's passed a 1D memoryview, call the implementation function;
- если ему передан скаляр, создайте массив 1x1 и вызовите функцию реализации;
- Если ему передан массив multi-D, то либо сгладьте его для функции реализации, либо выполните итерацию по строкам, вызывая функцию реализации для каждой строки.
Далее следует быстрая реализация. Это предполагает, что вы хотите, чтобы функция применялась к каждому элементу входного массива (и вам нужен выходной массив того же размера). Выбранная иллюстративная функция просто добавляет 1 к каждому значению. Он также использует numpy местами (а не просто типизированные представления памяти), что я считаю разумным:
cimport cython
import numpy as np
import numbers
@cython.boundscheck(False)
cdef double[:] _plus_one_impl(double[:] x):
cdef int n
cdef double[:] output
output = x.copy()
for n in range(x.shape[0]):
output[n] = x[n]+1
return output
def plus_one(x):
if isinstance(x,numbers.Real): # check if it's a number
return _plus_one_impl(np.array([x]))[0]
else:
try:
return _plus_one_impl(x)
except ValueError: # this gets thrown if conversion fails
if len(x.shape)<2:
raise ValueError('x could not be converted to double [:]')
output = np.empty_like(x) # output is all numpy, whatever the input is
for n in range(x.shape[0]): # this loop isn't typed, so is likely to be pretty slow
output[n,...] = plus_one(x[n,...])
return output
Этот код, вероятно, в некоторых случаях будет несколько медленным (например, двумерный массив с коротким вторым измерением).
Однако моя настоящая рекомендация — изучить ufuncs numpy, которые предоставляют интерфейс для эффективного достижения такого рода вещей. (См. http://docs.scipy.org/doc/numpy-dev/user/c-info.ufunc-tutorial.html). К сожалению, они сложнее, чем Cython.
I want to use static typing, but I don't know the type at compile time
- person cel   schedule 07.04.2015