2017-08-30 2 views
0

J'ai une très grande base de données en lecture seule et je veux faire un calcul, donc je fais un multiprocessing.map et définissez l'ensemble de données comme global. Cependant, cela implique-t-il que pour chaque processus, le programme copiera l'ensemble de données séparément (il sera donc rapide et partagé)?multiprocessing.map en python avec très grand objet en lecture seule?

+0

Notez que Si vous avez déjà créé des threads, il est complètement dangereux d'utiliser le multitraitement.Si un verrou aléatoire était verrouillé par un autre thread (et qu'il y avait un * lot * de verrous), les processus forkés se verrouilleraient lorsqu'ils essaieraient d'y accéder. – o11c

Répondre

1

Si je comprends bien vous ne serez pas un avantage en essayant d'utiliser multiprocessing.map sur un Pandas DataFrame parce que la trame de données est construit sur NumPy ndarray structures et NumPy libère déjà le GIL, échelles au matériel SMP, utilise des instructions machine vectorisées là où elles sont disponibles et ainsi de suite. Comme vous le dites, vous pourriez subir une consommation massive de RAM et une copie de données ou une surcharge de mémoire partagée sur les structures DataFrame sans aucun bénéfice. Considération de la performance sur la combinaison de NumPy et multiprocessing module de Python sont discutés dans ce SO Question: Multiprocessing.Pool makes Numpy matrix multiplication slower.

Le fait que vous traitez cette trame de données en lecture seule est intéressante car elle suggère que vous pouvez écrire le code autour os.fork() qui, en raison de la sémantique VACHE OS (copy-on-write) à la fourche () appel système, devrait être un moyen peu coûteux de partager les données avec les processus enfants, permettant à chacun d'ensuite analyser la date de diverses façons. (Tout code qui écrit sur les données déclencherait l'attribution de nouvelles pages et la copie, bien sûr).

Le module de multitraitement utilise l'appel système fourche () sous le capot (au moins sur Unix, Linux et systèmes similaires). Si vous créez et remplissez entièrement cette grande structure de données (DataFrame) avant d'appeler l'une des fonctions multiprocessing ou instanciez l'un de ses objets créant des sous-processus, vous pouvez accéder aux copies du DataFrame dont chaque processus a hérité implicitement . Je n'ai pas le temps de concocter un peu de code de test en ce moment; mais cela pourrait fonctionner. En ce qui concerne la consolidation de vos résultats à un processus parent ou délégué ... vous pouvez le faire à l'aide de n'importe quel mécanisme IPC (communications inter-processus). Si vous étiez en mesure de partager implicitement les données en les initialisant avant d'appeler des méthodes de forcing multitraitement, vous pourrez peut-être instancier simplement un multiprocessing.Queue et en lui fournissant des résultats. A défaut, personnellement, je considérerais juste de mettre en place une instance de Redis soit sur le même système ou sur tout autre système sur ce segment LAN. Redis est très efficace et extrêmement facile à configurer et à maintenir, avec des API et des modules Python (avec un support automatique/transparent pour hiredis pour la désérialisation haute performance des résultats Redis). Redis peut également faciliter la distribution de votre application sur plusieurs nœuds si vos besoins vous amènent dans cette direction. Bien sûr, d'ici là, vous pourriez également utiliser PySpark qui peut offrir de nombreuses fonctionnalités qui se mappent assez bien de Pandas DataFrames à Apache Spark jeux RDD (ou Spark SQL "DataFrames").Voici un article à ce sujet il y a quelques années: Databricks: From Pandas to Apache Spark's DataFrames.

En général, le but d'Apache Spark est de distribuer des calculs de données sur des nœuds distincts; ceci est intrinsèquement plus évolutif que de les répartir entre les cœurs au sein d'une même machine. (Ensuite, les préoccupations se résument à E/S aux noeuds de sorte que chacun peut obtenir ses morceaux de l'ensemble de données chargées. C'est un problème qui est bien adapté à HDFS.

J'espère que cela aide.

0

Chaque sous-processus aura ses propres ressources, donc cela implique. Plus précisément, chaque sous-processus copiera une partie de la base de données originale, déterminée par votre implémentation.

Mais sera-t-il rapide puis partagé? Je ne suis pas sûr. À moins que votre dataframe n'implémente un verrou w/r, en lire un partagé ou en lire un séparés sont les mêmes. Mais pourquoi une base de données doit verrouiller l'opération de lecture? Cela n'a pas de sens.