hpc:gpu
Skirtumai
Čia matote skirtumus tarp pasirinktos versijos ir esamo dokumento.
Next revision | Previous revisionNext revisionBoth sides next revision | ||
hpc:gpu [2021/12/16 10:57] – sukurtas eduardas | hpc:gpu [2022/01/31 17:11] – linp | ||
---|---|---|---|
Linija 1: | Linija 1: | ||
- | Info apie GPU skaičiavimus | + | ====== Paketinis užduočių vykdymas su GPU (SLURM) ====== |
+ | |||
+ | Norint pasinaudoti PST skaičiavimo resursais su GPU reikės formuoti užduočių skriptus (.sh): | ||
+ | |||
+ | |||
+ | Pavyzdys, bandant patikrinti ar jum suteikta GPU. | ||
+ | Sukuriamas failas gpu.txt su indikatoriumi ir vykdymo laiko momentu: | ||
+ | |||
+ | <code shell test_gpu.sh> | ||
+ | #!/bin/sh | ||
+ | #SBATCH -p gpu | ||
+ | #SBATCH -n1 | ||
+ | #SBATCH --gres gpu | ||
+ | |||
+ | source gpu_env/ | ||
+ | python3 test.py | ||
+ | </ | ||
+ | |||
+ | Pasinagrinėkime pavyzdį paeilučiui: | ||
+ | <code shell> | ||
+ | $ #SBATCH -p gpu | ||
+ | </ | ||
+ | nukreipiama į PST su vaizdo plokščių resursais skaičiavimo resursą. | ||
+ | |||
+ | <code shell> | ||
+ | $ #SBATCH -n1 | ||
+ | </ | ||
+ | nurodome, koks CPU poreikis bus reikalingas | ||
+ | |||
+ | <code shell> | ||
+ | $ #SBATCH --gres gpu | ||
+ | </ | ||
+ | nurodome, koks GPU poreikis bus reikalingas (esant N GPU poreikiui būtų nurodoma gpu:N). | ||
+ | |||
+ | |||
+ | <code shell> | ||
+ | $ source gpu_env/ | ||
+ | </ | ||
+ | pasiruošiame aplinką darbui (pirmą kartą ją reikia sukurti atskirai žr. aplinka.sh) | ||
+ | |||
+ | <code shell> | ||
+ | $ python3 test.py | ||
+ | </ | ||
+ | Kviečiame savo kodo skriptą, atlikti užduočiai su Python | ||
+ | |||
+ | |||
+ | |||
+ | Čia iškviečiamo Python kalbos skripto kodas, iškviečiant Pytorch biblioteką ir patikrinat GPU prieigą, kurios dažniausiai reikia kuriant mašininio mokymo modelius. | ||
+ | |||
+ | <code shell test.py> | ||
+ | import torch | ||
+ | import time | ||
+ | |||
+ | val = torch.cuda.is_available() | ||
+ | |||
+ | f = open(" | ||
+ | ts = time.time() | ||
+ | f.write(" | ||
+ | f.close() | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | Čia iškviečiamo Python kalbos skripto kodas, iškviečiant Pytorch biblioteką ir patikrinat GPU prieigą, kurios dažniausiai reikia kuriant mašininio mokymo modelius. | ||
+ | |||
+ | <code shell aplinka.sh> | ||
+ | # | ||
+ | |||
+ | python3 -m venv gpu_env | ||
+ | |||
+ | # pirmą kartą susirašome reikiamas bibliotekas savo projektui pvz: | ||
+ | |||
+ | pip3 install wheel | ||
+ | pip3 install pillow scikit-image | ||
+ | pip3 install numba | ||
+ | pip3 install torch==1.10.0+cu113 torchvision==0.11.1+cu113 torchaudio==0.10.0+cu113 -f https:// | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | ====== GPU išnaudojimas lygiagretinant kodą su Numba biblioteka ====== | ||
+ | |||
+ | === Įvadas į CUDA Python su Numba === | ||
+ | |||
+ | CUDA skaičiavimo biblioteka įgalina programų pagreitinimą, | ||
+ | |||
+ | **Numba** yra " | ||
+ | |||
+ | |||
+ | === Pavyzdžiai darbas su Numba: Pvz. 1 === | ||
+ | |||
+ | Pavydžiui, realizuokime Pitagorinę sudėtį: | ||
+ | |||
+ | https:// | ||
+ | |||
+ | <code shell> | ||
+ | # importuojame jit kompiliatorių | ||
+ | from numba import jit | ||
+ | import numpy as np | ||
+ | import math | ||
+ | |||
+ | # Sintaksė @jit ekvivalentu užrašui `hypot = jit(hypot)`. | ||
+ | @jit | ||
+ | def hypot(x, y): | ||
+ | x = abs(x); | ||
+ | y = abs(y); | ||
+ | t = min(x, y); | ||
+ | x = max(x, y); | ||
+ | t = t / x; | ||
+ | return x * math.sqrt(1+t*t) | ||
+ | |||
+ | |||
+ | # Bandome | ||
+ | hypot(3.0, 4.0) | ||
+ | |||
+ | |||
+ | # Nesukompiliuotos su *jit* funkcijos iškvietimas | ||
+ | ypot.py_func(3.0, | ||
+ | |||
+ | </ | ||
+ | |||
+ | Gauti metodų vykdymo laikus galėtume atitinkamai pvz: | ||
+ | |||
+ | <code shell> | ||
+ | timeit hypot.py_func(3.0, | ||
+ | |||
+ | timeit hypot(3.0, 4.0) | ||
+ | </ | ||
+ | |||
+ | === Pavyzdžiai darbas su Numba: Pvz. 2 === | ||
+ | |||
+ | Parašykime programą pi vertinimui Monte Karlo metodu (žr. https:// | ||
+ | |||
+ | <code shell> | ||
+ | from numba import jit | ||
+ | import random | ||
+ | |||
+ | @jit | ||
+ | def monte_carlo_pi(nsamples): | ||
+ | acc = 0 | ||
+ | for i in range(nsamples): | ||
+ | x = random.random() | ||
+ | y = random.random() | ||
+ | if (x**2 + y**2) < 1.0: | ||
+ | acc += 1 | ||
+ | return 4.0 * acc / nsamples | ||
+ | |||
+ | |||
+ | |||
+ | import matplotlib.pyplot as plt | ||
+ | |||
+ | |||
+ | nsamples = 1000000 | ||
+ | |||
+ | n = [2**i for i in range(0, 20)] | ||
+ | pi_values = [monte_carlo_pi(i) for i in n] | ||
+ | |||
+ | plt.plot(n, pi_values) | ||
+ | plt.axhline(y=np.pi, | ||
+ | plt.xscale(' | ||
+ | plt.xlabel(" | ||
+ | plt.ylabel(" | ||
+ | </ | ||
+ | |||
+ | |||
+ | Gauti metodų vykdymo laikus galėtume atitinkamai pvz: | ||
+ | |||
+ | <code shell> | ||
+ | timeit monte_carlo_pi(nsamples) | ||
+ | |||
+ | timeit monte_carlo_pi.py_func(nsamples) | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Kaip Numba veikia? | ||
+ | |||
+ | Numba kompiliatorius atsivželgia į duomenų tipus ir optimizuoja tarpinius skaičiavimu (angl. Intermediate representation (IR)) | ||
+ | |||
+ | |||
+ | ### **Numba** optimizuojant kodą skirtą GPU naudojant **NumPy** universalias funkcijas (ufuncs) | ||
+ | Toliau laikysime GPU programavimo aprėpyje jog dirbsime su NumPy universaliomis funkcijas (arba ufuncs) - t.y. standartinės bibliotekos funkcijos žr. dokumentaciją: | ||
+ | |||
+ | === Pavyzdžiai darbas su Numba: Pvz. 3 === | ||
+ | |||
+ | <code shell> | ||
+ | |||
+ | import numpy as np | ||
+ | |||
+ | a = np.array([1, | ||
+ | b = np.array([10, | ||
+ | |||
+ | np.add(a, b) | ||
+ | |||
+ | |||
+ | # Universalios funkcijos veikia su vektoriais ir skaičiais | ||
+ | np.add(a, 100) | ||
+ | |||
+ | |||
+ | # Matriciniu atveju, vektoriai taikomi sąrašo elementams t.y. eilutėms | ||
+ | c = np.arange(4*4).reshape((4, | ||
+ | print(' | ||
+ | |||
+ | np.add(b, c) | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | === Universalių funkcijų kūrimas ir optimizavimas | ||
+ | |||
+ | |||
+ | Svarbu suprasti, jog norint kurti universalias fukcijas, tokias turime ir naudoti. Šiuo atveju, tam mum bus reikalinkas metodas *vectorize*. | ||
+ | |||
+ | Šiame pačiame pirmame pavyzdyje naudosime *vectorize*, | ||
+ | |||
+ | |||
+ | |||
+ | <code shell> | ||
+ | from numba import vectorize | ||
+ | |||
+ | @vectorize | ||
+ | def add_ten(num): | ||
+ | return num + 10 | ||
+ | |||
+ | nums = np.arange(10) | ||
+ | nums | ||
+ | |||
+ | add_ten(nums) | ||
+ | |||
+ | # Dabar norint išnaudoti **GPU** optimizavimą mum reikia | ||
+ | @vectorize([' | ||
+ | def add_ufunc(x, | ||
+ | return x + y | ||
+ | |||
+ | add_ufunc(a, | ||
+ | </ | ||
+ | |||
+ | |||
+ | Gauti metodų vykdymo laikus galėtume atitinkamai pvz: | ||
+ | |||
+ | <code shell> | ||
+ | timeit np.add(b, c) # NumPy - CPU | ||
+ | |||
+ | timeit add_ufunc(b, | ||
+ | </ | ||
+ | |||
+ | # Ant CPU veikia greičiau :) | ||
+ | # 1. duomenys per maži | ||
+ | # 2. operacijos primityvios | ||
+ | # 3. kopijuojame duomenis į GPU | ||
+ | # 4. naudojame didelius duomenis (int64) | ||
+ | |||
+ | |||
+ | === Pavyzdžiai darbas su Numba: Pvz. 4 === | ||
+ | |||
+ | Panagrinėkime sudėtingesnį atvejį f(x|\mu, \sigma) = \frac{e^{-((x-\mu)/ | ||
+ | |||
+ | <code shell> | ||
+ | |||
+ | |||
+ | import math | ||
+ | |||
+ | SQRT_2PI = np.float32((2*math.pi)**0.5) | ||
+ | |||
+ | @vectorize([' | ||
+ | def gaussian_pdf(x, | ||
+ | return math.exp(-0.5 * ((x - mean) / sigma)**2) / (sigma * SQRT_2PI) | ||
+ | |||
+ | |||
+ | |||
+ | import numpy as np | ||
+ | |||
+ | x = np.random.uniform(-3, | ||
+ | x = np.sort(x) | ||
+ | |||
+ | mean = np.float32(0.0) | ||
+ | sigma = np.float32(1.0) | ||
+ | |||
+ | |||
+ | f = gaussian_pdf(x, | ||
+ | |||
+ | |||
+ | |||
+ | plt.plot(x, f) | ||
+ | plt.xlabel(' | ||
+ | plt.ylabel(' | ||
+ | </ | ||
+ | |||
+ | Gauti metodų vykdymo laikus galėtume atitinkamai pvz: | ||
+ | |||
+ | <code shell> | ||
+ | timeit gaussian_pdf(x, | ||
+ | |||
+ | import scipy.stats | ||
+ | norm_pdf = scipy.stats.norm | ||
+ | timeit norm_pdf.pdf(x, | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | === Pavyzdžiai darbas su Numba: Pvz. 5 === | ||
+ | |||
+ | Tais atvejais, kai norime spartinti vektorinius skaičiavimus, | ||
+ | |||
+ | |||
+ | <code shell> | ||
+ | |||
+ | from numba import cuda | ||
+ | |||
+ | @cuda.jit(device=True) | ||
+ | def polar_to_cartesian(rho, | ||
+ | x = rho * math.cos(theta) | ||
+ | y = rho * math.sin(theta) | ||
+ | return x, y | ||
+ | |||
+ | @vectorize([' | ||
+ | def polar_distance(rho1, | ||
+ | x1, y1 = polar_to_cartesian(rho1, | ||
+ | x2, y2 = polar_to_cartesian(rho2, | ||
+ | |||
+ | return ((x1 - x2)**2 + (y1 - y2)**2)**0.5 | ||
+ | |||
+ | |||
+ | n = 1000000 | ||
+ | rho1 = np.random.uniform(0.5, | ||
+ | theta1 = np.random.uniform(-np.pi, | ||
+ | rho2 = np.random.uniform(0.5, | ||
+ | theta2 = np.random.uniform(-np.pi, | ||
+ | |||
+ | |||
+ | polar_distance(rho1, | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Plačiau apie GPU išnaudojimą | ||
+ | |||
+ | |||
+ | * [[https:// | ||
+ | |||
+ | * [[https:// |
hpc/gpu.txt · Keista: 2022/10/30 13:54 vartotojo linp