Grafuri de sarcini și metode de planificare

Programare paralelă cu Dask în Python

James Fulton

Climate Informatics Researcher

Vizualizarea unui graf de sarcini

# Create 2 delayed objects
delayed_num1 = delayed(my_square_function)(3)
delayed_num2 = delayed(my_square_function)(4)

# Add them
result = delayed_num1 + delayed_num2

# Plot the task graph result.visualize()

Diagramă care arată pașii necesari pentru calcularea rezultatului. my-square-function este rulată de două ori, iar cele două rezultate sunt transmise unei funcții de adunare. Aceasta returnează un singur rezultat.

Programare paralelă cu Dask în Python

Graf de sarcini suprapus

delayed_intermediate = delayed(my_square_function)(3)

# These two results both use delayed_intermediate_result
delayed_result1 = delayed_intermediate - 5
delayed_result2 = delayed_intermediate + 4
Programare paralelă cu Dask în Python

Graf de sarcini suprapus

delayed_result1.visualize()

Diagramă care arată graful de sarcini pentru rezultatul 1.

delayed_result2.visualize()

Diagramă care arată graful de sarcini pentru rezultatul 2.

Programare paralelă cu Dask în Python

Graf de sarcini suprapus

# Plot the task graph
dask.visualize(delayed_result1, delayed_result2)

Graf de sarcini care arată că rezultatul 1 și rezultatul 2 partajează un rezultat intermediar.

Programare paralelă cu Dask în Python

Multi-threading vs. procesare paralelă

Transferul datelor

Procesare paralelă
  • Procesele au propriul spațiu RAM
Multi-threading
  • Thread-urile utilizează același spațiu RAM
Programare paralelă cu Dask în Python

Multi-threading vs. procesare paralelă

# Run a sum on two big arrays
sum1 = delayed(np.sum)(big_array1)
sum2 = delayed(np.sum)(big_array2)

# Compute using processes
dask.compute(sum1, sum2)
  • Lent cu procesare paralelă

Diagrama arată că cele două array-uri dintr-un proces Python trebuie trimise la alte două procese Python.

Programare paralelă cu Dask în Python

Multi-threading vs. procesare paralelă

# Run a sum on two big arrays
sum1 = delayed(np.sum)(big_array1)
sum2 = delayed(np.sum)(big_array2)

# Compute using threads
dask.compute(sum1, sum2)
  • Rapid cu multi-threading

Diagrama arată că cele două array-uri nu trebuie copiate deloc.

Programare paralelă cu Dask în Python

GIL

Global interpreter lock - un singur thread poate citi scriptul Python la un moment dat

def sum_to_n(n):
    """Sums numbers from 0 to n"""
    total = 0
    for i in range(n+1):
        total += i
    return total
  • Multi-threading nu ajută aici
  • Procesarea paralelă da
sum1 = delayed(sum_to_n)(1000)
sum2 = delayed(sum_to_n)(1000)
Programare paralelă cu Dask în Python

Timpi de execuție - GIL

Trei diagrame Gantt care arată timpii de execuție pentru rularea unei funcții Python simple de 16 ori. Dintre cele trei metode de planificare, procesele au fost cele mai rapide.

Programare paralelă cu Dask în Python

Funcții care eliberează GIL-ul

  • De ex., funcția pd.read_csv() eliberează GIL-ul
df1 = delayed(pd.read_csv)('file1.csv')
df2 = delayed(pd.read_csv)('file2.csv')
Programare paralelă cu Dask în Python

Timpi de execuție - Încărcare date

Trei diagrame Gantt care arată timpii de execuție pentru încărcarea unui CSV de 16 ori. Dintre cele trei metode de planificare, thread-urile au fost cele mai rapide.

Programare paralelă cu Dask în Python

Rezumat

Thread-uri

  • Se inițiază foarte rapid
  • Partajează memoria cu sesiunea principală
  • Nu necesită transfer de memorie
  • Limitate de GIL, care permite unui singur thread să citească codul odată

Procese

  • Necesită timp și memorie pentru inițializare
  • Au zone de memorie separate
  • Transferul de date între ele și sesiunea Python principală este foarte lent
  • Fiecare are propriul GIL și nu trebuie să aștepte să citească codul
Programare paralelă cu Dask în Python

Să exersăm!

Programare paralelă cu Dask în Python

Preparing Video For Download...