[PYTHON] (Übersetzung) Von Arrow zu Pandas mit 10 GB / s

EINLEITUNG: Wes McKinney, Autor von Pandas, hat einen sehr interessanten Blog über Python-Datentools geschrieben. Ich fragte, ob ich ihn übersetzen und in der japanischen PyData-Community veröffentlichen könnte. Ich habe das erhalten, also werde ich es nach und nach übersetzen und veröffentlichen.

Von Arrow zu Pandas mit 10 GB / s

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

2016/12/27

Dieser Beitrag beschreibt die jüngsten Arbeiten mit Apache Arrow, um eine schnelle Konvertierung des generischen spaltenorientierten Arrow-Speichers in Pandas-Objekte zu ermöglichen.

Herausforderungen beim Erstellen von Pandas DataFrame-Objekten mit hoher Geschwindigkeit

Eine der Schwierigkeiten beim Erstellen eines Pandas DataFrame-Objekts mit hoher Geschwindigkeit besteht darin, dass die "native" interne Speicherstruktur komplexer ist als ein Wörterbuch oder eine Liste eindimensionaler NumPy-Arrays. Ich werde nicht darauf eingehen, warum diese Komplexität hier auftritt, aber ich hoffe, dass dies in der Arbeit von Pandas 2.0 bewältigt werden kann. Diese Komplexität besteht aus zwei Schichten:

Werfen wir einen Blick auf die Benchmarks, um eine Vorstellung von dem Overhead zu bekommen, der durch das Zusammenstellen entsteht. Betrachten Sie den Setup-Code, der ein Wörterbuch mit 100 float64-Arrays mit 1 GB Daten erstellt.

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)
}

Erstellen Sie dann einen DataFrame mit pd.DataFrame (Daten):

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

(Für diejenigen, die versuchen, es herauszufinden, sind dies 7,58 GB / s, und alles, was es tut, ist den internen Speicher zu kopieren)

Das Wichtigste dabei ist, dass Sie an dieser Stelle eine "native" Speicherdarstellung von Panda erstellen können (null ist NaN im Array), aber es ist eine Sammlung eindimensionaler Arrays. ist.

Pfeilspaltenorientierte Speicher-Pandas-Konvertierung

Ich bin seit der Geburt von Apache Arrow im Jahr 2016 tief in dieses Projekt involviert. Apache Arrow ist ein sprachunabhängiges speicherorientiertes Tool für spaltenorientierte Darstellung und Interprozesskommunikation (IPC). Apache Arrow unterstützt verschachtelte JSON-ähnliche Daten und ist als Baustein für die Erstellung schneller Analyse-Engines konzipiert.

Im Vergleich zu Pandas kann Arrow in einer von den Werten getrennten Bitmap eindeutig Nullwerte darstellen. Daher erfordert selbst die Umwandlung von Nullkopien in ein Wörterbuch von Arrays, die für Pandas geeignet sind, eine weitere Verarbeitung.

Eines meiner Hauptziele bei der Arbeit mit Arrow ist die Verwendung als Breitband-E / A-Pipe für das Python-Ökosystem. Die Interaktion mit JVMs, Datenbanksystemen und verschiedenen Dateiformaten kann mithilfe von Arrow als spaltenorientiertes Austauschformat erreicht werden. In diesem Anwendungsfall ist es wichtig, so schnell wie möglich zum Pandas DataFrame zurückkehren zu können.

Letzten Monat habe ich das Engineering abgeschlossen, um den Speicher von Arrow in großer Bandbreite aus der internen Blockstruktur von Pandas aufzubauen. Wenn Sie sich das Dateiformat von Feather ansehen, werden Sie feststellen, dass all dieser Prozess eng miteinander verbunden ist.

Kehren wir zu denselben Gigabyte an Daten wie zuvor zurück und fügen einige Nullen hinzu.

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

Konvertieren wir nun diesen DataFrame in eine Pfeiltabelle. Dadurch wird eine spaltenorientierte Darstellung von Arrow erstellt.

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

Rufen Sie die to_pandas-Methode der Tabelle auf, um zu pandas zurückzukehren. Es unterstützt Multithread-Konvertierungen. Lassen Sie uns also eine Single-Thread-Konvertierung durchführen und vergleichen.

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

Das sind 6,33 GB / s, was etwa 20% langsamer ist als der Aufbau auf einer reinen Speicherbasis. Auf meinem Desktop kann ich mit allen vier Kernen beschleunigen.

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

9,71 GB / s sind überhaupt keine Situation, in der mir die Hauptspeicherbandbreite meiner Consumer-Desktop-Hardware ausgeht (obwohl ich hier kein Experte bin).

Die Leistungssteigerungen durch Multithreading können auf verschiedenen Hardwarekomponenten noch dramatischer sein. Das Leistungsverhältnis auf meinem Desktop beträgt nur 1,53, auf meinem Laptop (der auch ein Quad-Core ist) 3,29.

Beachten Sie jedoch, dass die Arbeit mit numerischen Daten der beste Fall ist. Für Zeichenfolgen- und Binärdaten verwenden Pandas weiterhin Python-Objekte in ihrer Speicherdarstellung, jedoch mit dem zusätzlichen Overhead.

Auswirkungen auf die Zukunft und Roadmap

Sie können jetzt problemlos ein Array von Pfeilen, einen Stapel von Datensätzen (mehrere Arrays gleicher Länge) oder eine Tabelle (eine Sammlung von Stapeln von Datensätzen) aus einer Vielzahl von Quellen mit null Kopien erstellen, sodass diese Methode flexibel ist. Es ist jetzt möglich, Tabellendaten effizient zwischen Systemen zu verschieben. Jetzt, da Sie mit hoher Geschwindigkeit in Pandas konvertieren können, können Sie den gesamten Pandas DataFrame mit geringen Konvertierungskosten ignorieren (5-10 GB / s werden im Vergleich zur E / A-Leistung anderer Medien normalerweise ignoriert. Sie können es jetzt bekommen.

Ich werde einen weiteren Beitrag über die technischen Details des C ++ - E / A-Subsystems von Arrow schreiben, das einen geringen Overhead aufweist (und so viel wie möglich ohne Kopie verarbeitet).

Während wir uns entlang der Pandas 2.0-Roadmap bewegen, hoffen wir, den Aufwand für die Interaktion mit spaltenorientiertem Speicher wie Arrow weiter zu reduzieren (und in einigen Fällen auf Null zu setzen). Die einfachere Speicherdarstellung erleichtert auch anderen Anwendungen die Interaktion mit Pandas auf niedriger Ebene.

Recommended Posts

(Übersetzung) Von Arrow zu Pandas mit 10 GB / s
[Python] Erstellen Sie eine Tabelle von Pandas DataFrame zu Postgres
Summe von 1 bis 10
Kopieren von Dateien direkt von Amazon EC2 (Amazon Linux) nach S3
Kopieren Sie S3-Dateien mit GSUtil von Python nach GCS