Je suis tombé sur un drôle de comportement de la mémoire en travaillant avec numpy + cython, en essayant de récupérer les données d'un tableau numpy comme un tableau C, à utiliser dans une fonction sans GIL. J'ai regardé à la fois l'API des tableaux de cython et de numpy mais je n'ai pas trouvé d'explication. Considérez donc les lignes de code suivantes :
cdef np.float32_t *a1 = <np.float32_t *>np.PyArray_DATA(np.empty(2, dtype="float32"))
print "{0:x}".format(<unsigned int>a1)
cdef np.float32_t *a2 = <np.float32_t *>np.PyArray_DATA(np.empty(2, dtype="float32"))
print "{0:x}".format(<unsigned int>a2)[]
J'alloue deux tableaux numpy avec la fonction empty de numpy, et je veux récupérer un pointeur vers le tampon de données pour chacun d'eux. On pourrait s'attendre à ce que ces deux pointeurs pointent vers deux adresses mémoire différentes sur le tas, éventuellement espacées de 2*4 octets. Mais non, j'obtiens des pointeurs vers la même adresse mémoire, par ex.
>>>96a7aec0
>>>96a7aec0
Comment cela se fait-il ? J'ai réussi à contourner ce problème en déclarant mes tableaux numpy en dehors de l'appel PyArray_DATA, dans ce cas, j'obtiens ce que j'attends.
La seule explication à laquelle je peux penser est que je ne crée aucun objet Python en dehors de la portée de la fonction PyArray_DATA, et que l'appel de cette fonction n'incrémente pas le nombre de références de Python. Par conséquent, le GC récupère cet espace mémoire juste après, et le tableau suivant est alloué à l'adresse mémoire précédente maintenant libre. Quelqu'un de plus calé en Python que moi pourrait-il confirmer cela ou donner une autre explication ?