Jaki jest zalecany sposób przydzielania pamięci na widok pamięci wpisanej?
TheDokumentacja Cythona dotycząca widoków wpisanej pamięci wypisz trzy sposoby przypisywania do widoku pamięci wpisanej:
z surowego wskaźnika C,odnp.ndarray
iodcython.view.array
.Załóżmy, że nie mam danych przekazanych do mojej funkcji cython z zewnątrz, ale zamiast tego chcę przydzielić pamięć i zwrócić ją jakonp.ndarray
, którą z tych opcji wybrałem? Załóżmy również, że rozmiar tego bufora nie jest stałą czasu kompilacji, tj. Nie mogę przydzielić na stosie, ale musiałbymmalloc
dla opcji 1.
Trzy opcje wyglądałyby więc następująco:
from libc.stdlib cimport malloc, free
cimport numpy as np
from cython cimport view
np.import_array()
def memview_malloc(int N):
cdef int * m = <int *>malloc(N * sizeof(int))
cdef int[::1] b = <int[:N]>m
free(<void *>m)
def memview_ndarray(int N):
cdef int[::1] b = np.empty(N, dtype=np.int32)
def memview_cyarray(int N):
cdef int[::1] b = view.array(shape=(N,), itemsize=sizeof(int), format="i")
Co mnie dziwi, to we wszystkich trzech przypadkachCython generuje sporo kodu na alokację pamięci, w szczególności na wywołanie__Pyx_PyObject_to_MemoryviewSlice_dc_int
. Sugeruje to (i mogę się tutaj mylić, mój wgląd w wewnętrzne funkcjonowanie Cythona jest bardzo ograniczony), że najpierw tworzy obiekt Pythona, a następnie „rzuca” go do widoku pamięci, co wydaje się niepotrzebne.
A prosty benchmark nie ujawnia znaczącej różnicy między tymi trzema metodami, przy czym 2. jest najszybsza przy niewielkim marginesie.
Która z trzech metod jest zalecana? Czy istnieje inna, lepsza opcja?
Dalsze pytanie: Chcę w końcu zwrócić wynik jakonp.ndarray
, po przepracowaniu tego widoku pamięci w funkcji. Czy typowy widok pamięci jest najlepszym wyborem, czy raczej użyję starego interfejsu bufora, jak poniżej, aby utworzyćndarray
na pierwszym miejscu?
cdef np.ndarray[DTYPE_t, ndim=1] b = np.empty(N, dtype=np.int32)