Grafi di task e metodi di scheduling

Programmazione parallela con Dask in Python

James Fulton

Climate Informatics Researcher

Visualizzare un task graph

# Crea 2 oggetti delayed
delayed_num1 = delayed(my_square_function)(3)
delayed_num2 = delayed(my_square_function)(4)

# Somma
result = delayed_num1 + delayed_num2

# Visualizza il task graph result.visualize()

Un diagramma mostra i passaggi per calcolare il risultato. my-square-function gira due volte e i due output vanno a una funzione add. Questa restituisce un output.

Programmazione parallela con Dask in Python

Task graph sovrapposti

delayed_intermediate = delayed(my_square_function)(3)

# Entrambi i risultati usano delayed_intermediate_result
delayed_result1 = delayed_intermediate - 5
delayed_result2 = delayed_intermediate + 4
Programmazione parallela con Dask in Python

Task graph sovrapposti

delayed_result1.visualize()

Un diagramma che mostra il task graph per il risultato 1.

delayed_result2.visualize()

Un diagramma che mostra il task graph per il risultato 2.

Programmazione parallela con Dask in Python

Task graph sovrapposti

# Visualizza il task graph
dask.visualize(delayed_result1, delayed_result2)

Un task graph che mostra che risultato 1 e risultato 2 condividono un risultato intermedio.

Programmazione parallela con Dask in Python

Multi-threading vs. elaborazione parallela

Spostare i dati

Elaborazione parallela
  • I processi hanno il proprio spazio RAM
Multi-threading
  • I thread usano lo stesso spazio RAM
Programmazione parallela con Dask in Python

Multi-threading vs. elaborazione parallela

# Somma su due array grandi
sum1 = delayed(np.sum)(big_array1)
sum2 = delayed(np.sum)(big_array2)

# Calcola con processi
dask.compute(sum1, sum2)
  • Lento con elaborazione parallela

Il diagramma mostra che i due array creati in un processo Python devono essere inviati a due altri processi Python.

Programmazione parallela con Dask in Python

Multi-threading vs. elaborazione parallela

# Somma su due array grandi
sum1 = delayed(np.sum)(big_array1)
sum2 = delayed(np.sum)(big_array2)

# Calcola con thread
dask.compute(sum1, sum2)
  • Veloce con multi-threading

Il diagramma mostra che i due array non devono essere copiati.

Programmazione parallela con Dask in Python

Il GIL

Global Interpreter Lock: un solo thread può leggere lo script Python alla volta

def sum_to_n(n):
    """Somma i numeri da 0 a n"""
    total = 0
    for i in range(n+1):
        total += i
    return total
  • Qui il multi-threading non aiuta
  • L’elaborazione parallela sì
sum1 = delayed(sum_to_n)(1000)
sum2 = delayed(sum_to_n)(1000)
Programmazione parallela con Dask in Python

Esempi di tempi - GIL

Tre diagrammi di Gantt mostrano i tempi per eseguire una semplice funzione Python 16 volte. Tra tre metodi di scheduling, i processi sono i più veloci.

Programmazione parallela con Dask in Python

Funzioni che rilasciano il GIL

  • Ad es., la funzione pd.read_csv() rilascia il GIL
df1 = delayed(pd.read_csv)('file1.csv')
df2 = delayed(pd.read_csv)('file2.csv')
Programmazione parallela con Dask in Python

Esempi di tempi - Caricamento dati

Tre diagrammi di Gantt mostrano i tempi per eseguire 16 volte una funzione che carica dati da un CSV. Tra tre metodi di scheduling, i thread sono i più veloci.

Programmazione parallela con Dask in Python

Riepilogo

Thread

  • Avvio molto rapido
  • Condividono la memoria con la sessione principale
  • Niente trasferimento di memoria
  • Limitati dal GIL: un thread legge il codice alla volta

Processi

  • Richiedono tempo e memoria per l’avvio
  • Hanno pool di memoria separati
  • Trasferimento dati molto lento tra loro e con la sessione Python principale
  • Ognuno ha il proprio GIL, quindi non devono alternarsi nella lettura del codice
Programmazione parallela con Dask in Python

Ayo berlatih!

Programmazione parallela con Dask in Python

Preparing Video For Download...