(Traduction) De Arrow aux pandas à 10 Go / s

INTRODUCTION: Wes McKinney, auteur de pandas, a écrit un blog très intéressant sur les outils de données Python, j'ai donc demandé si je pouvais le traduire et le publier dans la communauté japonaise PyData. J'ai reçu ceci, donc je vais le traduire petit à petit et le publier.

De Arrow aux pandas à 10 Go / s

(Original: http://wesmckinney.com/blog/high-perf-arrow-to-pandas/)

2016/12/27

Cet article décrit le travail récent avec Apache Arrow pour permettre la conversion rapide de la mémoire générique orientée colonne Arrow en objets pandas.

Les défis de la construction d'objets DataFrame pandas à grande vitesse

L'une des difficultés de la construction d'un objet pandas DataFrame à grande vitesse est que la structure de la mémoire interne "native" est plus complexe qu'un dictionnaire ou une liste de tableaux NumPy unidimensionnels. Je n'entrerai pas dans les raisons de cette complexité ici, mais j'espère que cela pourra être géré dans le travail de pandas 2.0. Il y a deux niveaux à cette complexité:

Jetons un coup d'œil aux repères pour avoir une idée des frais généraux qui découlent de la mise en place. Considérez le code de configuration qui crée un dictionnaire de 100 tableaux float64 contenant 1 Go de données.

import numpy as np
import pandas as pd
import pyarrow as pa

type_ = np.dtype('float64')
DATA_SIZE = (1 << 30)
NCOLS = 100
NROWS = DATA_SIZE / NCOLS / np.dtype(type_).itemsize

data = {
    'c' + str(i): np.random.randn(NROWS)
    for i in range(NCOLS)
}

Créez ensuite un DataFrame avec pd.DataFrame (data):

>>> %timeit df = pd.DataFrame(data)
10 loops, best of 3: 132 ms per loop

(Pour ceux qui essaient de le comprendre, c'est 7,58 Go / sec, et il ne fait que copier la mémoire interne)

L'important ici est qu'à ce stade, vous pouvez construire une représentation mémoire "native" de panda (null sera NaN dans le tableau), mais c'est une collection de tableaux unidimensionnels. est.

Conversion de mémoire orientée colonne vers pandas

Je suis profondément impliqué dans ce projet depuis la naissance d'Apache Arrow en 2016. Apache Arrow est un outil de représentation et de communication interprocessus (IPC) orienté colonne en mémoire indépendant du langage. Apache Arrow prend en charge les données imbriquées de type JSON et est conçu pour être un élément de base pour la création de moteurs d'analyse rapides.

Comparé aux pandas, Arrow peut clairement représenter des valeurs nulles dans un bitmap séparé des valeurs. Par conséquent, même la conversion d'une copie zéro en un dictionnaire de tableaux adapté aux pandas nécessite un traitement supplémentaire.

L'un de mes principaux objectifs en travaillant avec Arrow est de l'utiliser comme canal d'E / S à large bande pour l'écosystème Python. L'interaction avec les JVM, les systèmes de base de données et divers formats de fichiers peut être obtenue en utilisant Arrow comme format d'échange orienté colonnes. Dans ce cas d'utilisation, il est important de pouvoir revenir le plus rapidement possible au pandas DataFrame.

Le mois dernier, j'ai terminé l'ingénierie pour construire la mémoire d'Arrow dans une large bande passante à partir de la structure de bloc interne des pandas. Si vous regardez le format de fichier de Feather, vous verrez que tout ce processus est étroitement lié.

Revenons aux mêmes gigaoctets de données qu'avant et ajoutons quelques valeurs nulles.

>>> df = pd.DataFrame(data)
>>> df.values[::5] = np.nan

Convertissons maintenant ce DataFrame en table Arrow. Cela crée une représentation de Arrow orientée colonnes.

>>> table = pa.Table.from_pandas(df)
>>> table
<pyarrow.table.Table at 0x7f18ec65abd0>

Pour revenir aux pandas, appelez la méthode to_pandas de la table. Il prend en charge les conversions multithreads, alors faisons une conversion monothread et comparons.

>>> %timeit df2 = table.to_pandas(nthreads=1)
10 loops, best of 3: 158 ms per loop

C'est 6,33 Go / s, ce qui est environ 20% plus lent que de construire sur une base memcpy pure. Sur mon bureau, je peux accélérer avec les quatre cœurs.

>>> %timeit df2 = table.to_pandas(nthreads=4)
10 loops, best of 3: 103 ms per loop

9,71 Go / s n'est pas du tout une situation où je manque de bande passante de la mémoire principale sur mon matériel de bureau grand public (bien que je ne sois pas un expert ici).

Les gains de performances du multithreading peuvent être encore plus spectaculaires sur différents matériels. Le rapport de performance sur mon bureau n'est que de 1,53, mais sur mon ordinateur portable (qui est également un quad core), il est de 3,29.

Cependant, gardez à l'esprit que travailler avec des données numériques est le meilleur des cas. Pour les données chaîne et binaires, les pandas continueront à utiliser des objets Python dans la représentation mémoire, mais avec la surcharge supplémentaire.

Impact sur l'avenir et feuille de route

Vous pouvez désormais créer facilement un tableau de flèches, un lot d'enregistrements (plusieurs tableaux de la même longueur) ou une table (une collection de lots d'enregistrements) à partir d'une variété de sources avec zéro copie, cette méthode est donc flexible. Il est désormais possible de déplacer efficacement les données tabulaires entre les systèmes. Maintenant que vous pouvez convertir en pandas à grande vitesse, vous pouvez ignorer le pandas complet DataFrame à un faible coût de conversion (5 à 10 Go / s sont généralement ignorés par rapport aux performances d'E / S d'autres supports. Vous pouvez maintenant l'obtenir.

J'écrirai un autre article sur les détails techniques du sous-système d'E / S C ++ d'Arrow, qui a une faible surcharge (et des processus avec zéro copie autant que possible).

Au fur et à mesure que nous avançons dans la feuille de route de pandas 2.0, nous espérons réduire davantage (et dans certains cas zéro) la surcharge de l'interaction avec la mémoire orientée colonne comme Arrow. La représentation plus simple de la mémoire permettra également aux autres applications d'interagir plus facilement avec les pandas à bas niveau.

Recommended Posts

(Traduction) De Arrow aux pandas à 10 Go / s
[python] Créer une table de pandas DataFrame vers postgres
Somme de 1 à 10
Copie de fichiers directement d'Amazon EC2 (Amazon Linux) vers S3
Copier les fichiers S3 de Python vers GCS à l'aide de GSUtil