Je lis je lis le Documentation pour la gestion de la mémoire dans Python C Extensions , et aussi loin que je peux dire, il ne semble pas vraiment y avoir beaucoup de raison d'utiliser malloc code> plutôt que pymem_malloc code>. Disons que je veux allouer un tableau qui ne doit pas être exposé au code source Python et sera stocké dans un objet qui sera recruté. Y a-t-il une raison d'utiliser masloc code>? P>
3 Réponses :
De mon expérience Ecrire des fonctions MATLAB .MEX, je pense que le plus gros facteur déterminant de savoir si vous utilisez MALLOC ou non est la portabilité. Dites que vous avez un fichier d'en-tête qui effectue une charge d'une charge utile à l'aide des types de données C internes uniquement (aucune interaction de l'objet Python nécessaire, donc aucun problème à l'aide de MALLOC), et vous vous rendez soudainement réalisez que vous souhaitez porter ce fichier d'en-tête sur une base de code différente qui a Rien à voir avec Python Que soit (peut-être que c'est un projet écrit purement en C), à l'aide de MALLOC, serait évidemment une solution beaucoup plus portable. P>
Mais pour votre code qui est purement une extension Python, ma réaction initiale serait de s'attendre à ce que la fonction Native C soit plus rapide. Je n'ai aucune preuve pour atteindre cet objectif :) p>
Vous avez raison de s'attendre à ce que la fonction C Native C est meilleure. La chose est qu'ils sont tous deux natifs c fonctions. :-)
Eh bien, je suppose qu'ils sont ... Belle technicité :) Je suppose que je voulais dire plus que je m'attendais à ce que le système d'allocation de la mémoire native de C soit plus rapide que l'autochtone C implémenté pour le système d'allocation de mémoire de Python: P
J'ai utilisé Malloc et Pymem_Malloc. Mes points de repère ont montré une différence de performance négligible entre les deux. Pymem_Malloc peut avoir été plus rapide mais je ne pense pas que la différence était de manière statistique. YMMV, bien sûr.
De mon expérience dans Matlab, vous devez utiliser mxmalloc i> si possible ou n'oubliez pas de rétrograder sur toute erreur
Il est parfaitement correct pour les extensions pour allouer la mémoire avec MALLOC ou d'autres allocateurs système. C'est normal et inévitable pour de nombreux types de modules - la plupart des modules qui enveloppent d'autres bibliothèques, ce qui ne savent rien sur Python, provoquera des allocations indigènes quand elles se produisent dans cette bibliothèque. (Certaines bibliothèques vous permettent de contrôler suffisamment l'affectation pour éviter cela; la plupart ne le font pas.) P>
Il y a un inconvénient grave à l'utilisation de pymem_malloc: vous devez tenir la gil à l'utiliser. Les bibliothèques indigènes souhaitent souvent libérer le gil lors de calculs à forte intensité de la CPU ou en faisant des appels pouvant bloquer, comme des E / S. Besoin de verrouiller le gil avant que les allocations puissent être quelque part entre très gênant et un problème de performance. P>
Utiliser les wrappers de Python pour une allocation de mémoire permet d'utiliser le code de débogage de la mémoire de Python. Avec des outils comme Valgrind, je doute de la valeur réelle de cela, cependant. P>
Vous devrez utiliser ces fonctions si une API l'exige; Par exemple, si une API est passée un pointeur qui doit être attribué à ces fonctions, il peut donc être libéré avec eux. En empêchant une raison explicite comme celle-là pour les utiliser, je m'enlève d'une allocation normale. P>
edit strong>: mixte sans le / * malloc. Notez que nbytes == 0 essaie
Pour retourner un pointeur non nul, distinct p>
En outre, il existe une note de conseil sur le Ne jamais mélanger les appels vers pymem_ avec
Appels vers la plate-forme Malloc / Realloc /
calloc / gratuitement. Par exemple, sous Windows
Différentes dlls peuvent finir par utiliser
différents tas, et si vous utilisez
Pymem_malloc vous obtiendrez la mémoire
du tas utilisé par le python
Dll; Cela pourrait être une catastrophe si vous
libre () 'ed qui directement dans votre propre
extension. En utilisant pympem_free à la place
assure que Python peut retourner la
mémoire au bon tas. Comme un autre
Exemple, en mode pymalloc_debug,
Python enveloppe tous les appels vers tous pymem_
et pyObject_ la mémoire fonctionne dans
emballages de débogage spéciaux qui ajoutent
informations de débogage supplémentaires à
Blocs de mémoire dynamique. Le système
Les routines n'ont aucune idée de quoi faire
avec ce genre de choses et le python
Les wrappers n'ont aucune idée de quoi faire
avec des blocs bruts obtenus directement par
les routines du système alors. P>
blockquote> Ensuite, il existe des réglages spécifiques à Python à l'intérieur Le complexe petits objets ( Ce commentaire sur le code source explique comment l'appel pymem_malloc code> et pyObject_malloc code> corrections; ils sont deux appels différents. pymalloc_debug code> macro activé, pymem_malloc code> est un alias de MALLOC () code>, ayant un cas particulier : appeler pymem_malloc code> Pour allouer que zéro Byte retournera un pointeur non nulle, tandis que Malloc (zero_bytes) pourrait renvoyer une valeur nulle ou élever une erreur système ( Référence de code source ): P>
pymem.h code> fichier d'en-tête : p>
pymem_malloc CODE> Strike> pyObject_malloc code>, une fonction utilisée non seulement pour les extensions C mais pour Toutes les allocations dynamiques lors de l'exécution d'un programme Python, comme 100 * 234 code>, str (100) code> ou 10 + 4j code>: p> xxx pré> précédent () code> Les instances sont de petits objets alloués sur un pool dédié. p> pymem_malloc code> grève> pyobject_malloc code> est assez efficace car il est fait à partir d'une piscine 8 octets bloqués, un pool existant pour chaque taille de bloc. Il existe également des pages et des blocs Arenas pour des allocations plus grandes. P> pyObject_malloc code> est optimisé: p> /*
* The basic blocks are ordered by decreasing execution frequency,
* which minimizes the number of jumps in the most common cases,
* improves branching prediction and instruction scheduling (small
* block allocations typically result in a couple of instructions).
* Unless the optimizer reorders everything, being too smart...
*/
Les allocateurs indigènes sont déjà extrêmement optimisés. Cela n'a aucune incidence sur les modules d'extension - si quelque chose, ce n'est que des frais généraux supplémentaires pour ralentir les choses.
@Glenn Avez-vous des chiffres difficiles à soutenir cela? Les documents sont assez vastes et détaillés pour être juste un "frais de tête pour ralentir".
J'ai de l'expérience et du bon sens: l'allocator système affecte la vitesse de l'ensemble du système, de sorte que beaucoup d'efforts vont les optimiser. Si vous prétendez que Python s'améliore à ce sujet - pour une utilisation du module d'extension, non seulement le cas particulier du noyau de python de bas niveau - c'est votre prétention de sauvegarder.