Vai al contenuto principale
Python
Data Science

Primi passi con l’accelerazione GPU di Polars: query 13 volte più veloci

Scopri come usare il recente motore GPU di Polars, basato su NVIDIA RAPIDS cuDF, per ottenere prestazioni di query più veloci su grandi dataset.
Thalia Barrera's photo
Thalia Barrera
Aggiornato · 11 min leggi

Scopri con l'IA

ChatGPTClaudePerplexity

Crea il tuo account gratuito

Pratica and corso your progress.

Continua Con Google
Continuando, accetti i nostri Termini di utilizzo, la nostra Informativa sulla privacy e che i tuoi dati siano conservati negli Stati Uniti.

Di recente ho avuto il privilegio di accedere in anteprima al motore GPU di Polars, basato su NVIDIA RAPIDS cuDF, prima della sua open beta. Questa funzionalità all’avanguardia ha il potenziale per trasformare i flussi di lavoro sui dati accelerando le operazioni di Polars fino a 13 volte con le GPU NVIDIA. Se lavori con dataset su larga scala in Python, è una svolta che non vuoi perderti.

In questo post ti spiegherò tutto ciò che devi sapere sul nuovo motore GPU di Polars e ti fornirò una guida passo passo per iniziare!

Immagine che mostra affiancati i loghi di Polars e NVIDIA

Polars: una libreria DataFrame ad alte prestazioni

Al centro della maggior parte dei flussi di lavoro in data science c’è il DataFrame, una struttura tabellare flessibile e intuitiva per gestire dati strutturati. In poche parole, chiunque faccia data science ha lavorato con i DataFrame.

I DataFrame consentono una manipolazione, esplorazione e analisi dei dati semplice, offrendo un’interfaccia familiare e coerente per pulire, filtrare, raggruppare e trasformare i dati.

Tuttavia, nel contesto dei big data, le librerie tradizionali di DataFrame possono peccare in prestazioni e scalabilità: è qui che entra in gioco Polars.

Polars è una libreria DataFrame veloce ed efficiente che è diventata rapidamente una delle scelte migliori per l’elaborazione dati ad alte prestazioni. Scritto da zero in Rust, Polars è progettato per operare vicino all’hardware, ottimizzando velocità e uso delle risorse senza dipendere da componenti esterni.

Il post Introduzione a Polars è un’ottima risorsa per iniziare a usare la libreria in Python.

Immagine con un grafico che confronta le prestazioni delle librerie DataFrame più popolari

Confronto delle prestazioni delle librerie DataFrame più popolari. Fonte immagine: Polars

I benchmark pubblicati da Polars, mostrati nell’immagine sopra, dimostrano che Polars supera costantemente altre librerie come Pandas, Modin, PySpark e Dask su diverse query. Questi risultati evidenziano la forza di Polars come opzione più veloce per l’elaborazione dati ad alte prestazioni.

Ma com’è possibile? Ecco alcune caratteristiche che rendono Polars estremamente veloce:

  • Scritto in Rust: utilizza programmazione di basso livello per eseguire le operazioni, restando vicino all’hardware.
  • Flessibilità I/O: supporto di prima classe per tutti i livelli di archiviazione dati, locali, in cloud o connessi a database.
  • API intuitiva: l’API di Polars ti consente di scrivere query in modo intuitivo. L’ottimizzatore di Polars determina internamente il piano di esecuzione più efficiente, riducendo al minimo tempi e memoria.
  • Elaborazione out-of-core: la streaming API di Polars consente di elaborare dataset troppo grandi per entrare in memoria.
  • Esecuzione parallela: Polars utilizza automaticamente tutti i core CPU disponibili, suddividendo i carichi tra di essi senza configurazioni aggiuntive, massimizzando la potenza di calcolo della tua macchina.
  • Motore di query vettorializzato: Polars elabora le query in modo vettoriale usando Apache Arrow, un formato di dati colonnare, e SIMD (Single Instruction, Multiple Data) per ottimizzare ulteriormente l’uso della CPU.

E con il recente annuncio dell’open beta del motore GPU di Polars, sta per diventare ancora più veloce!

Capire l’integrazione con NVIDIA RAPIDS cuDF

La domanda di elaborazione e analisi dei dati più veloce è cresciuta esponenzialmente negli ultimi anni, man mano che i dataset sono arrivati a centinaia di milioni o persino miliardi di righe. Per affrontare questa sfida, la data science ha visto un passaggio crescente dall’elaborazione basata su CPU al calcolo accelerato da GPU. È qui che entra in gioco NVIDIA RAPIDS cuDF.

NVIDIA RAPIDS è una suite open-source di librerie che abilita la data science e l’analisi accelerate da GPU. Al suo nucleo, RAPIDS è progettato per semplificare i flussi di lavoro sui dati sfruttando il massiccio parallelismo delle GPU NVIDIA per accelerare compiti tipicamente vincolati alla CPU. 

All’interno di RAPIDS, cuDF è la libreria responsabile delle operazioni sui DataFrame. cuDF estende l’astrazione familiare del DataFrame alla memoria della GPU, consentendo l’integrazione nei flussi di lavoro senza ampie modifiche al codice. La libreria supporta tutte le principali operazioni che i data scientist eseguono sui DataFrame: filtro, aggregazione, join e ordinamento, tutto alimentato dalla GPU per la velocità.

NVIDIA e Polars hanno appena annunciato l’open beta del motore GPU di Polars per Python, basato su RAPIDS cuDF. Questa nuova funzionalità segna un passo avanti significativo per l’elaborazione dati ad alte prestazioni, offrendo fino a 13 volte flussi di lavoro più rapidi agli utenti Polars con GPU NVIDIA!

Immagine della progettazione di alto livello dell’API di Polars che include un motore GPU

Progettazione di alto livello dell’API di Polars, incluso un motore GPU. Fonte immagine: Polars

Con l’aggiunta del motore GPU, gli utenti di Polars possono decidere su quale motore eseguire i loro carichi di lavoro. L’ottimizzatore di Polars supporta tutti i motori, determinando dinamicamente quali query possono essere eseguite su GPU o CPU.

Il motore GPU di Polars: una svolta

Ora hai un po’ di contesto su Polars e sulla libreria NVIDIA RAPIDS cuDF, su come si integrano e come sono rese disponibili tramite l’API Python di Polars. Ma cosa significa tutto questo per sviluppatori e data scientist?

Ecco un riepilogo di ciò che abilita il motore GPU di Polars:

  • Integrazione con la Lazy API di Polars in Python: puoi semplicemente passare engine="gpu" all’operazione collect() della Lazy API di Polars, abilitando l’elaborazione su GPU senza modifiche significative al codice.
  • Elaborazione interattiva di grandi dataset: il motore GPU è pensato per rendere interattiva l’elaborazione di centinaia di milioni di righe. Con una singola GPU puoi gestire volumi di dati enormi che richiederebbero soluzioni più complesse e lente.
  • Ottimizzato per l’efficienza: il motore GPU di Polars sfrutta appieno l’ottimizzatore di Polars per garantire un’esecuzione il più efficiente possibile, riducendo tempi e uso di memoria.
  • Fallback su CPU senza interruzioni: nei casi in cui specifiche query non siano supportate su GPU, il motore include un fallback su CPU. In questo modo il flusso di lavoro non si interrompe, tornando automaticamente alla CPU quando necessario.

E i risultati finora? Vediamo. 

Immagine con risultati di benchmark che mostrano come il motore GPU di Polars acceleri l’elaborazione dati fino a 13 volte

Il motore GPU di Polars accelera l’elaborazione dei dati fino a 13 volte. Fonte immagine: Polars

Il benchmark sopra dimostra le impressionanti capacità del motore GPU di Polars, accelerando le query fino a 13 volte.

Tuttavia, è importante notare che usare Polars su GPU non è sempre garantito essere più veloce rispetto alla CPU, in particolare per query semplici che non sono computazionalmente intensive. In questi casi, le prestazioni sono spesso limitate dalla velocità di lettura dei dati dal disco: quando le operazioni di input/output (I/O) sono il collo di bottiglia, l’accelerazione GPU offre un vantaggio minore.

Detto ciò, il motore GPU offre accelerazioni significative per operazioni dati più complesse, rendendolo uno strumento prezioso per i team che gestiscono grandi dataset o query con join, group-by e processamento di stringhe.

L’interazione tra CPU e GPU

Una delle caratteristiche più interessanti di questa nuova integrazione è la sua flessibilità. Come accennato, l’ottimizzatore può passare tra esecuzione su CPU e su GPU in base alla complessità delle tue query. Ma come avviene esattamente questa transizione?

Polars senza accelerazione GPU

Quando esegui Polars sulla CPU, il motore segue una pipeline strutturata e altamente ottimizzata per eseguire le operazioni sui dati. Il processo prevede approssimativamente i seguenti passaggi:

  1. DSL (domain-specific language): il motore Polars crea innanzitutto una traccia di query strutturata dal tuo codice, simile all’albero sintattico di un linguaggio di programmazione. Questa traccia definisce la sequenza di operazioni da eseguire, come filtrare, raggruppare e aggregare.
  2. IR (intermediate representation): successivamente, Polars converte la traccia di query in un piano di esecuzione dettagliato, assicurandosi che tutte le operazioni siano corrette e che gli schemi dei dati combacino. Questo passaggio getta le basi di come Polars elaborerà i dati.
  3. Ottimizzatore: l’ottimizzatore migliora il piano di esecuzione riordinando le operazioni e rimuovendo passaggi non necessari. Ad esempio, i filtri possono essere spostati prima di join o aggregazioni per ridurre prima possibile la dimensione del dataset. Questa ottimizzazione garantisce che il piano sia il più efficiente possibile prima dell’esecuzione.
  4. IR ottimizzata: dopo l’ottimizzazione, il piano migliorato è finalizzato e pronto per essere elaborato dal motore Polars. Questo piano è il blueprint di come Polars eseguirà ogni operazione sui dati.
  5. Motore in-memory di Polars (esecuzione su CPU): infine, il motore in-memory di Polars esegue il piano ottimizzato interamente sulla CPU. Nonostante le ottimizzazioni ad alte prestazioni di Polars, questo passaggio può richiedere tempo con dataset di grandi dimensioni, poiché le CPU elaborano i dati in modo sequenziale o con parallelismo limitato.

Polars con accelerazione GPU

Quando abiliti l’accelerazione GPU passando engine="gpu" al metodo .collect(), il processo in superficie resta essenzialmente lo stesso, ma con controlli e ottimizzazioni aggiuntivi dietro le quinte per determinare quanto carico può essere trasferito sulla GPU tramite cuDF:

  1. DSL (domain-specific language): come in modalità CPU, Polars inizia creando una traccia di query strutturata dal tuo codice. Questa traccia è la stessa sia che tu stia eseguendo su CPU sia su GPU, e cattura le operazioni che vuoi eseguire.
  2. IR (intermediate representation): Polars converte la traccia in un piano di esecuzione, verificando la correttezza e la validità degli schemi dei dati. In questa fase l’IR resta neutrale, poiché il motore non ha ancora deciso se le operazioni saranno gestite dalla CPU o dalla GPU.
  3. Ottimizzatore: l’ottimizzatore lavora come per l’esecuzione su CPU, riordinando le operazioni per la massima efficienza e rimuovendo i passaggi ridondanti. A questo punto, il piano è ancora ottimizzato per l’esecuzione generale.
  4. IR ottimizzata: il piano ottimizzato è finalizzato come per l’esecuzione su CPU. Tuttavia, con l’accelerazione GPU attivata, il motore verifica ora se parti di questo piano possono essere spostate sulla GPU.
  5. Callback cuDF (verifica GPU): è qui che avviene la magia! Il callback di cuDF determina se la GPU può gestire il piano di esecuzione. Alcune operazioni si prestano naturalmente all’accelerazione GPU, altre meno. Il callback modifica il piano per usare la GPU nelle operazioni supportate.
  6. Motore in-memory di Polars (esecuzione su GPU e CPU): infine, il motore in-memory di Polars esegue il piano. La GPU gestisce le query che possono essere accelerate, mentre le query non gestibili dalla GPU tornano alla CPU.

Questo modello di esecuzione ibrido—dove GPU e CPU sono usate in tandem—rende Polars estremamente flessibile. Benefici dell’accelerazione GPU senza rinunciare alla compatibilità per le query non supportate su GPU. Il post di rilascio di Polars lo spiega in maggior dettaglio tecnico.

Primi passi con il motore GPU di Polars

Finalmente, la parte più entusiasmante! In questa sezione ti guiderò nei passaggi necessari per configurare l’ambiente e iniziare a sfruttare l’elaborazione dati accelerata dalla GPU.

Il modo più semplice per partire è seguire questo notebook Google Colab. 

Colab offre un uso GPU gratuito ma limitato, particolarmente utile se non hai accesso immediato a una GPU. Se usi il notebook fornito, partiamo dal punto 2 qui sotto, quindi puoi saltare i passaggi precedenti.

Prerequisiti

Prima di installare il motore GPU di Polars, assicurati che il tuo sistema soddisfi i requisiti per NVIDIA RAPIDS cuDF. Puoi consultare le specifiche di sistema necessarie, inclusa la compatibilità GPU e i requisiti dei driver, nella pagina di documentazione di RAPIDS.

Per iniziare con il motore GPU di Polars, è buona pratica creare un ambiente virtuale per isolare le dipendenze del progetto. 

In questo esempio uso conda, ma sentiti libero di utilizzare il tuo gestore di pacchetti preferito.

Oltre a Python, puoi includere JupyterLab nell’ambiente per l’esplorazione e lo sviluppo interattivi dei dati, particolarmente utile per eseguire piccoli snippet di codice e analizzare i dataset al volo.

conda create -n polars-gpu -c conda-forge python=3.11 jupyterlab

Dopo aver creato l’ambiente virtuale, attivalo con:

conda activate polars-gpu

Ora abilitiamo l’accelerazione GPU installando Polars e il motore GPU. Questo imposterà anche cuDF e altre dipendenze necessarie per usare le GPU NVIDIA:

pip install -U polars[gpu] --extra-index-url=https://pypi.nvidia.com

Una volta installato il motore GPU di Polars, usare Polars su GPU sarà simile a lavorare con la CPU, ma con risultati molto più rapidi per flussi di lavoro complessi o con molti dati.

Come spiegato in precedenza, il motore di Polars ottimizza automaticamente il piano di esecuzione, sfruttando appieno la GPU NVIDIA per velocizzare le operazioni e ridurre al minimo l’uso di memoria. Per le query che non supportano l’accelerazione GPU, il motore GPU di Polars esegue un fallback su CPU senza interruzioni, garantendo la continuità del flusso di lavoro.

Mettiamo il motore all’opera con alcuni semplici esempi!

Esecuzione di alcune query con il motore GPU di Polars

Per questa dimostrazione useremo un dataset da 22 GB di transazioni finanziarie simulate da Kaggle. NVIDIA ospita il dataset su un bucket Google Cloud Storage (GCS), garantendo velocità di download elevate.

Per iniziare, scarica il dataset:

!wget https://storage.googleapis.com/rapidsai/polars-demo/transactions.parquet -O transactions.parquet

Poiché questo dataset proviene da Kaggle, è soggetto a una licenza e termini d’uso specifici per i dataset Kaggle.

Carichiamo il dataset con Polars e ispezioniamo lo schema:

import polars as pl
from polars.testing import assert_frame_equal

transactions = pl.scan_parquet("transactions.parquet")
transactions.collect_schema()

Ecco l’output:

Schema([('CUST_ID', String),
        ('START_DATE', Date),
        ('END_DATE', Date),
        ('TRANS_ID', String),
        ('DATE', Date),
        ('YEAR', Int64),
        ('MONTH', Int64),
        ('DAY', Int64),
        ('EXP_TYPE', String),
        ('AMOUNT', Float64)])

Ora calcoliamo il volume totale delle transazioni sommando la colonna AMOUNT. Prima proviamo senza accelerazione GPU:

transactions.select(pl.col("AMOUNT").sum()).collect()

Output:

AMOUNT
f64
3.6183e9

È un volume totale molto alto! Eseguiamo la stessa query sulla GPU:

transactions.select(pl.col("AMOUNT").sum()).collect(engine="gpu")

Output:

AMOUNT
f64
3.6183e9

Per operazioni semplici come questa, CPU e GPU producono lo stesso risultato con velocità simili, perché la query non è abbastanza intensiva da trarre grande vantaggio dalla GPU. La GPU però brillerà con query più complesse.

Passiamo a una query più complessa. In questa query raggruppiamo le transazioni per ID cliente (CUST_ID), sommiamo gli importi totali delle transazioni e poi ordiniamo i risultati per i maggiori spender. 

Per prima cosa, eseguiamola sulla CPU:

%%time
res_cpu = (
   transactions
   .group_by("CUST_ID")
   .agg(pl.col("AMOUNT").sum())
   .sort(by="AMOUNT", descending=True)
   .head()
   .collect()
)
res_cpu

Ecco l’output:

CPU times: user 4.63 s, sys: 3.75 s, total: 8.38 s
Wall time: 6.04 s
CUST_ID
AMOUNT
str
f64
"CA9UYOQ5DA"
2.0290e6
"CJUK2MTM5Q"
1.8115e6
"CYXX1NBIKL"
1.8082e6
"C6ILEYAYQ9"
1.7961e6
"CCNBC305GI"
1.7274e6

Ora eseguiamo la stessa query sulla GPU:

%%time
res_gpu = (
   transactions
   .group_by("CUST_ID")
   .agg(pl.col("AMOUNT").sum())
   .sort(by="AMOUNT", descending=True)
   .head()
   .collect(engine=”gpu”)
)
res_gpu

Output:

CPU times: user 347 ms, sys: 0 ns, total: 347 ms
Wall time: 353 ms
shape: (5, 2)
CUST_ID
AMOUNT
str
f64
"CA9UYOQ5DA"
2.0290e6
"CJUK2MTM5Q"
1.8115e6
"CYXX1NBIKL"
1.8082e6
"C6ILEYAYQ9"
1.7961e6
"CCNBC305GI"
1.7274e6

Come si vede, usare la GPU per query più complesse offre guadagni notevoli, riducendo il tempo di esecuzione da 6,04 secondi su CPU a soli 353 millisecondi su GPU!

Questo esempio dimostra la potente spinta prestazionale che il motore GPU di Polars offre per le operazioni su larga scala. 

Puoi trovare esempi più avanzati nel relativo notebook Colab.

Conclusione

Il motore GPU di Polars, basato su NVIDIA RAPIDS cuDF, porta notevoli miglioramenti di velocità, con elaborazioni dei dati fino a 13 volte più rapide per operazioni complesse. Per dataset su larga scala, Polars offre un chiaro vantaggio rispetto alle librerie di DataFrame tradizionali.

Anche se non tutte le query trarranno lo stesso beneficio dall’accelerazione GPU, Polars resta uno strumento potente per chi lavora con grandi quantità di dati. La facilità di integrazione, unita al modello di esecuzione ibrido CPU-GPU, rende Polars un forte candidato per i flussi di lavoro moderni sui dati.

Se vuoi potenziare le tue competenze di manipolazione dei dati, soprattutto con Pandas, ti consiglio vivamente questi corsi:

Queste risorse ti daranno basi solide che si integrano con le potenti capacità di strumenti come Polars!

FAQ

Che tipo di query traggono maggiore beneficio dall’accelerazione GPU in Polars?

L’accelerazione GPU in Polars offre i maggiori incrementi di velocità per le query compute-bound che coinvolgono operazioni come join, group-by e processamento di stringhe. Questi tipi di attività richiedono molta computazione e sono quelli in cui il parallelismo della GPU dà il meglio, con velocità fino a 13 volte superiori rispetto alla CPU. Le query più semplici o limitate dall’I/O possono non vedere lo stesso miglioramento.

L’accelerazione GPU sarà sempre più veloce dell’uso della CPU?

No, non sempre. Sebbene l’accelerazione GPU velocizzi notevolmente le operazioni compute-heavy, come aggregazioni complesse e join, le query limitate dall’I/O—dove il collo di bottiglia è la lettura e scrittura dei dati su disco—potrebbero non beneficiare altrettanto. In questi casi, la GPU non offre vantaggi significativi rispetto alla CPU e i tempi di esecuzione possono risultare simili.

Devo riscrivere le mie query Polars per usare il motore GPU?

No, non devi riscrivere le tue query. Il motore GPU di Polars si integra perfettamente con i flussi di lavoro esistenti. Ti basta passare engine="gpu" al metodo collect() per abilitare l’accelerazione GPU. Se una parte della query non è supportata dal motore GPU, verrà eseguito automaticamente un fallback sulla CPU senza necessità di modifiche da parte tua.

Posso usare il motore GPU di Polars su qualsiasi macchina?

Per usare il motore GPU di Polars, ti serve una macchina con GPU NVIDIA compatibili con RAPIDS cuDF, parte delle librerie CUDA-X. Se la tua macchina non ha una GPU compatibile, puoi usare servizi cloud come Amazon SageMaker Studio Lab, Google Colab o PaperSpace che offrono accesso gratuito o a pagamento a risorse GPU.


Thalia Barrera's photo
Author
Thalia Barrera
LinkedIn

Thalia Barrera è Senior Data Science Editor presso DataCamp, con un master in Informatica e oltre dieci anni di esperienza nel software e nell’ingegneria dei dati. Thalia ama semplificare i concetti tecnologici per ingegneri e data scientist tramite post sul blog, tutorial e video corsi.

Argomenti
Python
Data Science

Approfondisci data science e Python con questi corsi!

Corso

Python intermedio per sviluppatori

2 ore
70.2K
Immergiti nell'ecosistema Python, scopri i moduli e i pacchetti e impara a scrivere funzioni personalizzate!
Vedi i dettagliInizia Il Corso

Crea il tuo account gratuito

Pratica and corso your progress.

Continua Con Google
Continuando, accetti i nostri Termini di utilizzo, la nostra Informativa sulla privacy e che i tuoi dati siano conservati negli Stati Uniti.
Mostra altro
Correlato

blog

Che cos'è Snowflake? Guida per principianti alla piattaforma dati cloud

Esplora le basi di Snowflake, la piattaforma dati cloud. Scopri la sua architettura, le sue funzionalità e come integrarla nelle tue pipeline di dati.
Tim Lu's photo

Tim Lu

12 min

blog

Tokenizzazione nel NLP: come funziona, sfide e casi d'uso

Guida al preprocessing NLP nel machine learning. Copriamo spaCy, i transformer di Hugging Face e come funziona la tokenizzazione in casi d'uso reali.
Abid Ali Awan's photo

Abid Ali Awan

10 min

blog

I 15 migliori server MCP remoti che ogni AI builder dovrebbe conoscere nel 2026

Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Abid Ali Awan's photo

Abid Ali Awan

15 min

Mostra altro