Módosítások

Intel Xeon Phi

2 651 bájt hozzáadva, 2017. május 9., 09:15
automatikus kódátvitel
Az oldalon található információk segítséget nyújtanak a HPC felhasználóinknak, hogy alkalmazásaikat miként portolhatják valamint optimalizálhatják a hatékonyabb futást szem előtt tartva Intel Xeon Phi koprocesszor kártyákon.
 
{{INFO|Egy 10 alkalmas, angol nyelvű Xeon Phi programozás tutoriál videóanyaggal és példaprogrammal elérhető a [[http://colfaxresearch.com/how-16-04/ Colfax oldalán]]}}
 
==Hardver bemutatása==
====közvetlen natív használat====
A natív mód arra szolgál, hogy a MIC kártyára lefordított alkalmazásunkat felmásoljuk a kártyára, majd belépünk SSH-n a kártyára és azon futtatjuk a bináris kódunkat. <br />
Ez Biztonsági okokból a legegyszerűbb használati mód, ugyanis nincs más dolgunk, csak a '''-mmic''' kapcsolót használni a fordításnál és a fordító egy máris a MIC architektúrára kész bináris készít nekünkközvetlen natív használat az NIIF HPC infrastruktúrán nem elérhető. <br/>Workflow a következő lenne:# Alkalmazás megírása. például [[Média:hello.cc|''hello.cc'']]# Alkalmazás fordítása <br/> <pre>icpc -o hello-MIC -mmic hello.cc</pre># Másolás a MIC kártyára <br/> <pre>scp hello-MIC mic0:</pre># belépés a kártyára <br/> <pre>ssh mic0</pre># Alkalmazás futtatása <br/> <pre>./hello-MIC</pre>
===b) támogatott, de nem preferált használat===
# Alkalmazás megírása. például [[Média:hello.cc|''hello.cc'']]
# Alkalmazás fordítása <br/> <pre>icpc -o hello-MIC -mmic hello.cc</pre>
# A tool futásához szükséges library-k megadása <br> <pre>export SINK_LD_LIBRARY_PATH=/opt/intel/composerxe-<verzió>/compiler/lib/mic</pre>
# Alkalmazás futtatása <br/> <pre>micnativeloadex hello-MIC</pre>
:{| class="wikitable"
|-
| BUDAPEST2[cn10] phi (0)$ export SINK_LD_LIBRARY_PATH=/opt/intel/composerxe-2011.4.191/compiler/lib/mic <br/>BUDAPEST2[cn10] phi (0)$ micnativeloadex hello-MIC <br/>Hello world! I have 244 logical cores.<br/>BUDAPEST2[cn10] phi (0)$
|}
Intel MKL használat esetén a SINK_LD_LIBRARY_PATH természetesen kiegészítendő az MKL könyvtárak elérésével.
<pre>intelhome=/opt/intel/compilers_and_libraries_2016.1.150/linux
export SINK_LD_LIBRARY_PATH=$intelhome/compiler/lib/mic:$intelhome/mkl/lib/mic</pre>
===c) támogatott módok===
</pre>
Ekkor minden memória területet 2x kell másolni, egyszer fel a kártyára, majd másodszor vissza a hoszt gépre, pedig elegendő lenne csak az eredmény vektort visszamásolni. Ezen optimalizálással egy későbbi fejezetben foglalkozunk. <p />
Futás során kaphatunk részletes riportot is, hogy pontosan milyen adatmozgatások történnek az alkalmazás futása során. Ehhez nincs szükség másra csak az '''OFFLOAD_REPORT''' környezeti változó megfelelő beállítása. A beállított értékek Automatic Offload esetén 1, 2 vagy , míg Compiler Assisted Offload esetén 1, 2 és 3 lehetnek, attól függően mennyire részletes riportot szeretnénk kapni. <br />
beállítás:
<pre>
Abban az esetben, ha 1 számítási node nem elég, MPI segítségével össze tudunk kötni több nodet, heterogén rendszert alkotva, és azokon alkalmazható a fenti Offload + OpenMP modell. <br />
[[Fájl:Mpi+offload+openmp.png|MPI elosztás valamint Offload modell és OpenMP]] <br />
 
 
==Phi használat slurm-mel==
Slurm esetén a mic opciót kell megadni a gres-knél. Amennyiben egynél több kártyára van szükség, akkor azt a ''mic:2''-vel lehetséges megadni. Ekkor két kártyát foglal le az ütemező a futtatandó feladatnak. <br />
Egy lehetséges feladat, amit srun-nal lehet a slurmben beküldeni. debrecen3 esetén a ''prod-phi'' particiót kell használni
 
<pre>
$ cat slurm_job_openmp_phi
 
#!/bin/bash
#SBATCH -A <PROJECT NEVE>
#SBATCH --job-name=<JOB NEVE>
#SBATCH --gres mic:2
#SBATCH --time=1:00:00
#SBATCH --partition=prod
#SBATCH -o slurm-%A.out
export OMP_NUM_THREADS=2
./runme_openmp_2phi
</pre>
Ekkor a feladat beküldése a következő paranccsal lehetséges.
<pre>
srun ./slurm_job_openmp_phi
</pre>
==Alkalmazások optimalizálása a kártyára==
====Párhuzamos szálak ütemezése====
OpenMp a szálak ütemezésére három féle módod kínál fel.
Módok:
* '''static''' (alapértelmezett): egyenletesen arányban egymás után elosztja a processzeket az indított szálakon, ezért a futási idő tetszőlegesen elhúzódhat, ha egyes processzek lassabban futnak le.
* '''dynamic''': minden esetben az első szabad szálra kerül a következő processz ütemezése, folyamatos kihasználtságot elérve, de "költséges" a sok-sok ütemezés
* '''guided''': Az előző két mód ötvözése. Nagyobb procesz számot ütemez az éppen szabad szálakra, melyek számát folyamatosan csökkenti a futás előre haladtával, hogy körülbelül egyszerre fejeződjön be minden szál futása, ezzel csökkentve a dynamic esetén magad ütemezési időráfordítást.
 
Mindhárom esetben megadható az egyszerre ütemezett processzek száma, amit a ''chunk'' értéke határoz meg. Ha megvan adva a chunk értéke, akkor az minden esetben annak megfelelő processzámot ütemez a szálakra.
Használata:
<pre>
#pragma omp parallel [schedule (<mode>,<chunk>) {...}
</pre>
====Szálak szinkronizációja====
Szála szinkronizálását többféle módon lehet megvalósítani, de ezen megoldások sajno jelentősen lelassítják a program futását.
* mutexxel: nagyon lassú, állandóan várnak egymásra a párhuzamos szálak
<pre>
#pragma omp parallel for
for (int i = 0; i < n; i++) {
#pragma omp critical
{ // kritikus szekció, csak egy szál hajthatja végre
total = total + i;
}
}
</pre>
 
* atomi művelet definiálása: sajnos még ez is lassú, de itt már nem olyan "erős" a szinkronizáció, ezért rendkívül sok limitációja van az itt használható atomi műveleteknek.
<pre>
* with mutexes (it is very slow, waiting always) #pragma omp parallel for for (int i = 0; i < n; i++) { #pragma omp critical { // Only one thread at a time can execute this section total = total + i; } } atomic * or with atomic operation (it also [very] slow, lot of limitations) #pragma omp parallel for for (int i = 0; i < n; i++) { // Lightweight synchronization #pragma omp atomic total += i; }
</pre>
=====Párhuzamos redukció=====
Az itt bemutatott eljárás gyorsabb mint a fenti szinkronizációs megoldás, de sajnos nem alkalmazható vektorokra! A redukciót a ''reduction(operation: scalar)'' formában kell megadni.
<pre>
int sum = 0;
#pragma omp parallel for reduction(+: sum)
for (int i = 0; i < n; i++) {
sum = sum + i;
}
</pre>
 
 
Tulajdonképpen a fenti problémakörre a következő minta ad megoldást. Ekkor egy külön változóban akkumuláltatjuk a szál általi összeget és ezen értékeke összegyűjtését végezzük csak atomi műveletként.
<pre>
(it is fast) BUT not for vector int total sum = 0; #pragma omp parallel { int sum_thr = 0;#pragma omp for reduction(+: total) //usage: reduction(operation: scalar) for (int i = 0; i < n; i++) { total sum_thr += total i; #pragma omp atomic sum + i= sum_thr; }
</pre>
====Ciklusok párhuzamosítása====
Ciklus párhuzamosítására a következő mintát szokás használni.
<pre>
#pragma omp parallel { // Code placed here will be executed by all threadsAz itt definiált forrást minden szál esetén végre fog hajtani . ... #pragma omp for [schedule (<mode>,<chunk>) for (int i = 0; i < n; i++) { // Ez a kódrész lesz párhuzamosítva ... iterations will be distributed across available threads } // ... } // és ez a köd is minden szál esetén végrehajtódik ... code placed here will be executed by all threads } modes: static, dynamic, guided chunk: integer value
</pre>
}
</pre>
[[Kategória: HPC]]
98
szerkesztés

Navigációs menü