hpc:gpu
Skirtumai
Čia matote skirtumus tarp pasirinktos versijos ir esamo dokumento.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
hpc:gpu [2022/01/31 16:46] – linp | hpc:gpu [2022/10/30 13:54] (esamas) – linp | ||
---|---|---|---|
Linija 1: | Linija 1: | ||
- | ====== Paketinis užduočių vykdymas (SLURM) ====== | + | ====== Paketinis užduočių vykdymas |
Norint pasinaudoti PST skaičiavimo resursais su GPU reikės formuoti užduočių skriptus (.sh): | Norint pasinaudoti PST skaičiavimo resursais su GPU reikės formuoti užduočių skriptus (.sh): | ||
- | + | Labai dažnai GPU mum reiks vykdant mašininio mokymo ir dirbtinio intelekto technologijų modeliams, pažiurėkime kaip pasiruošti PyTorch ir Tensorflow aplinkas ir patikrinti ar bibliotekos gali vykdyti kodą GPU spartinimu. | |
- | Pavyzdys, bandant patikrinti ar jum suteikta | + | ====== Skriptų su PyTorch ir GPU paleidimas per SLURM ====== |
- | Sukuriamas | + | |
+ | Programos vykdymo metu sukuriamas | ||
<code shell test_gpu.sh> | <code shell test_gpu.sh> | ||
Linija 13: | Linija 14: | ||
#SBATCH --gres gpu | #SBATCH --gres gpu | ||
- | source | + | . gpu_env/ |
python3 test.py | python3 test.py | ||
</ | </ | ||
Linija 35: | Linija 36: | ||
<code shell> | <code shell> | ||
- | $ source | + | $ . gpu_env/ |
</ | </ | ||
pasiruošiame aplinką darbui (pirmą kartą ją reikia sukurti atskirai žr. aplinka.sh) | pasiruošiame aplinką darbui (pirmą kartą ją reikia sukurti atskirai žr. aplinka.sh) | ||
Linija 74: | Linija 75: | ||
pip3 install pillow scikit-image | pip3 install pillow scikit-image | ||
pip3 install numba | pip3 install numba | ||
- | pip3 install torch==1.10.0+cu113 | + | pip3 install torch torchvision torchaudio |
</ | </ | ||
+ | |||
+ | |||
+ | ====== Skriptų su Tensorflow/ | ||
+ | |||
+ | Programos vykdymo metu sukuriamas failas gpu.txt su indikatoriumi ir vykdymo laiko momentu: | ||
+ | |||
+ | <code shell test_gpu_tf.sh> | ||
+ | #!/bin/sh | ||
+ | #SBATCH -p gpu | ||
+ | #SBATCH -n1 | ||
+ | #SBATCH --gres gpu | ||
+ | |||
+ | export PATH=$HOME/ | ||
+ | export CONDA_PREFIX=$HOME/ | ||
+ | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH: | ||
+ | . activate base | ||
+ | conda activate gpu_env | ||
+ | |||
+ | |||
+ | python3 test_tf.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> | ||
+ | $ export PATH=$HOME/ | ||
+ | $ export CONDA_PREFIX=$HOME/ | ||
+ | $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH: | ||
+ | $ . activate base | ||
+ | $ conda activate gpu_env | ||
+ | </ | ||
+ | pasiruošiame aplinką darbui (pirmą kartą ją reikia sukurti atskirai žr. aplinka_tf.sh) | ||
+ | |||
+ | <code shell> | ||
+ | $ python3 test_tf.py | ||
+ | </ | ||
+ | Kviečiame savo kodo skriptą, atlikti užduočiai su Python | ||
+ | |||
+ | |||
+ | |||
+ | Čia iškviečiamo Python kalbos skripto kodas, iškviečiant Tensorflow biblioteką ir patikrinat GPU prieigą, kurios dažniausiai reikia kuriant mašininio mokymo modelius. | ||
+ | |||
+ | <code shell test_tf.py> | ||
+ | import time | ||
+ | import tensorflow as tf | ||
+ | |||
+ | val = tf.test.is_gpu_available() | ||
+ | |||
+ | f = open(" | ||
+ | ts = time.time() | ||
+ | f.write(" | ||
+ | f.close() | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | Čia iškviečiamo Python kalbos skripto kodas, iškviečiant Tensorflow biblioteką ir patikrinat GPU prieigą, kurios dažniausiai reikia kuriant mašininio mokymo modelius. | ||
+ | |||
+ | <code shell aplinka_tf.sh> | ||
+ | #!/bin/bash | ||
+ | |||
+ | wget https:// | ||
+ | bash Miniconda3-latest-Linux-x86_64.sh | ||
+ | # yes - on install, no - in init, path default one | ||
+ | |||
+ | export PATH=~/ | ||
+ | conda create --name gpu_env python=3.9 | ||
+ | . activate base | ||
+ | conda activate gpu_env | ||
+ | conda install -c conda-forge cudatoolkit=11.7 cudnn=8.1.0 | ||
+ | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH: | ||
+ | |||
+ | |||
+ | # pirmؤ… kartؤ… susiraإ،ome reikiamas bibliotekas | ||
+ | pip3 install wheel | ||
+ | pip3 install pillow scikit-image | ||
+ | pip3 install tensorflow | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ====== 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.1643647606.txt.gz · Keista: 2022/01/31 16:46 vartotojo linp