Párhuzamosítás többmagos processzorok programozásához

Először hadd idézzem két idézetet más témákról.

Ha nem tudod, hogyan programozhatsz bármit, mint a BASIC, és nem tudod, hogyan kell párhuzamosítani a számítási folyamatokat, ez nem jelenti azt, hogy mások is nem tudják és nem tudják. És ha helyesen programozod a mellszobrot, a lehetőségek teljesen a szokásos modern személyzet erejéig vannak, és mindent megtesz, elég elfogadható időre.


[az üzenet címzettje]

Most a programom nem használ többmagos, azaz. Csak néhány programot futtathat a processzor magjainak számával anélkül, hogy növelné a működési időt.

Nyilvánvaló, hogy mindkét idézőjelben párhuzamot kell adni a számítási folyamatnak a többmagos processzorokkal rendelkező számítógépek végrehajtására szánt programokban.

Ki tud kipróbálni?

Nataly-Mak
Nekem is kevés ismerete van.
Az első dolog, amit mondok, megkülönböztetni fog a 3 párhuzamos szint.
1) Számítógépek között
2) A magok között
3) parancsszintű párhuzamosság.

Minden szinten használják a saját eszközeiket.

1) számítógépek között. Talán az adatok elemzésének legegyszerűbb módja. Tegyük fel, hogy számítógépes hálózattal rendelkezik. Csak másolja az adatokat és a programot a számítógépekre, és futtassa le a végrehajtásra. Miután megkaptad az eredményt. Az ilyen művek megtervezéséhez van egy tengeri program. Ha klasztert szeretne az interneten. Ezután még meg kell oldani az adatok és a rendszer védelmét. És az interneten lévő számítógépek is más.
2) A magok közötti párhuzamosság. Számítógépben nagyszámú számítási egység a legnagyobb CPU (CPU / CPU) és grafikus processzor (GPU / GPU). Minden processzor tartalmaz egy vagy több magot. A rendszermag különálló eszközként tekinthető meg, amelyen elindíthatja saját parancsát. Általában nem osztják meg a többprocesszoros és a többmagos hálózatot.

A különbség a közös busz jelenléte a megosztott memória eléréséhez.
Két típusú SMP és NUMA rendszer létezik.
Szimmetrikus többprocesszoros (angol szimmetrikus többprocesszoros, rövidítve SMP). - az építészet többprocesszoros számítógépek, melyek kevesebb, mint két azonos processzor csatlakozik a megosztott memóriát. Amikor belépünk egy osztott memória busz minden tiltva az egyidejű olvasás vagy írás nem lehetséges.

NUMA (nem egységes memória hozzáférés - "nem egységes memória hozzáférés" vagy nem egységes memória architektúra - "architektúra nem egységes memóriával".
Olyan architektúra, amelyben a memória különböző részeire való hozzáférés eltérő sebességgel rendelkezik. Ez az okos memóriaelosztásnak köszönhető, amikor a memóriába való bejutás blokkolatlanul megy, és hozzáférést biztosít a megosztáshoz a zárolással.

Ha figyelembe vesszük a CPU-t. A párhuzamosításhoz a kódot általában úgy oldják meg, hogy egy kernel párhuzamos kódját írják és több szálat hoznak létre. Általában van ilyen kód. Ezt a nyelvi szinten határozzák meg.
CreatThead (Thead);
Thead.Do (függvény);
funkció - egy szubrutin, amelyet több szálon hajtanak végre.
Ez a legprimitívebb. Vannak olyan fejlettebb dolgok, mint az OpenMP, ami megkönnyíti az írást.
Nincs semmi bonyolult. Csak gyakorolni kell, hogy tanulj párhuzamosan.
De a programozónak gondoskodnia kell a memória és a zárak eléréséről.


A GPU egy nagy teljesítményű számítástechnikai eszköz. A modern GP sokkal hatékonyabb, mint a CPU. Ezért érdekes használni számításokhoz. Még érdekesebb, ha egyszerre fut egy kódot a CPU-n és a GPU-n. CUDA és ATIStreem és mások erre a célra használatosak.
Az NVIDIA CUDA fejlesztése és az ATI ATIStreem fejlesztése. Ezért ugyanaz a kód a különböző gyártók kártyáin nehéz. Újraírásra van szükség. Azonban nem tudom a legújabb újításokat.


3) parancsszintű párhuzamosság.
A modern processzorok multiscaláris szerkezetűek. Mindegyik maghoz általában több ALU (Arithmetic Logic Device) tartozik. Bizonyos adatok és parancsok szervezésével a kernel több parancsot is végrehajthat párhuzamosan. Még mindig létezik olyan dolog, mint a SIMD.
A SIMD (angol egyszeri utasítás, több adat) a számítástechnikai számítások alapelve, amely lehetővé teszi az adatok szintjén a párhuzamosságot. Ha az adatokat csalókra csoportosítják, négy, nyolc. És egy parancs egy műveletet hajt végre az adatokon, a 2,4,8 ALU használatával.

És mi több, növelheti a végrehajtási időt többször (összesen a processzor két magjával)?

Igen, igen. Van egy jól ismert formula Amdahl törvény, ha a költségek aránya kicsi, akkor a nyereség lehet nagy. Mivel a processzor általában 2-4 magot tartalmaz, és minden mag tartalmaz 8,16-ot. ALU. A grafikus processzor több tucat, több száz, és több ezer ALU-t támogat. A GPU-ban az ALU-k rendszerint 4 kisebb gyakorisággal vannak csoportosítva, mint 8 mag.

Ha tudod, pascal. És írni fogsz Pascal / Delphi-ban.


Ó, jaj! Most nem tudom. Nagyon sokáig, amikor dolgoztam, Pascal ismerte és írta a programokat.
Most, egy hosszú szünet után, csak a BASIC-ot ismerem (lásd az első idézetet)
A QBASIC-on írok. Az svb kolléga nagyon jó pb5 fordítót talált számomra (mielőtt a tolmács munkájában).
Több tucat programot írtam különböző mágikus négyzetek létrehozására a fordító alatt, semmit, négyzeteket általában nem hoznak létre

// Használható adattípusok
const mx = 43;
típus
PNumbers = ^ TNumbers;
TNumbers = array [0..mx * mx-1] az int64-ből;
TMatrix = tömb [0..mx-1, 0..mx-1] az int64-ben;

típus
TAInteger = egész szám tömbje;

eljárás ViewSquare # 40; k: egész szám; ms: TMatrix; S: int64; p: boolean = false; a: boolean = false # 41 ;; túlterhelés
eljárás ViewSquare # 40; var F: Szövegfájl; k: egész szám; ms: TMatrix; S: int64; p: boolean = false; a: boolean = false # 41 ;; túlterhelés
eljárás ViewNumbers # 40; k: egész szám; S: int64; V: TNumbers # 41 ;;
eljárás ViewMatrix # 40; k: egész szám; V: TNumbers # 41 ;;

function GetCnk # 40; n, k: egész # 41 ;: int64;
eljárás: SetA # 40; var A: TNumbers; b: az int64 # 41 ;;
eljárás: SetM # 40; n: egész szám; var M: TMatrix; b: az int64 # 41 ;; túlterhelés
eljárás: SetM # 40; n: egész szám; var M: TMatrix; b: a 41. egész szám tömbje ;; túlterhelés
function toMatrix # 40; n: egész; A: TNumbers # 41 ;: TMatrix;
függvény CheckMS # 40; n: egész; m: TMatrix; var S: int64; var p, a: logikai # 41 ;: logikai;
eljárás ToMatrixRosser # 40; n: egész szám; A: TNumbers; var M: TMatrix # 41 ;;
function isMagic # 40; n: egész; M: TMatrix; var S: int64; var p: logikai # 41 ;: logikai;
függvény isPMagic # 40; n: egész; M: TMatrix; S: int64 # 41 ;: logikai;
eljárás RosserToMatrix # 40; n: egész szám; M: TMatrix; var A: TNumbers # 41 ;;
függvény isDifferent # 40; n: egész; M: TMatrix # 41 ;: logikai;
eljárás SetAInteger # 40; a: tömb egész szám; var ls: TAInteger # 41 ;;

eljárás: SetA # 40; var A: TNumbers; b: az int64 # 41 ;;
var i: egész szám;
kezdődik
töltőanyag # 40; A, sizeof # 40; A # 41;, 0 # 41 ;;
i: = alacsony # 40; b # 41; a nagy # 40; b # 41; kezdeni
A [i]: = b [i];
végén;
végén;

eljárás ViewSquare # 40; k: egész szám; ms: TMatrix; S: int64; p: boolean = false; a: boolean = false # 41 ;;
var i, j. integer;
kezdődik
írj # 40; k, ': [' # 41 ;;
ha p, akkor írja be a # 40; 'p' # 41 ;;
ha a, majd írja a # 40; "a" # 41 ;;
írjon # 40; ']:', S, ':' # 41 ;;
i: = 0-tól k-1-ig
a j: = 0-tól k-1-ig kezdődik
írjon # 40; ms [i, j] # 41 ;;
ha # 40; i végén;
writeln;
végén;

eljárás ViewSquare # 40; var F: Szövegfájl; k: egész szám; ms: TMatrix; S: int64; p: boolean = false; a: boolean = false # 41 ;;
var i, j. integer;
kezdődik
írjon # 40; F, k, ': [' # 41 ;;
ha p, akkor írja a # 40; F, 'p' # 41 ;;
ha a, akkor írj # 40; F, 'a' # 41 ;;
írjon # 40; F, ']:', S, ':' # 41 ;;
i: = 0-tól k-1-ig
a j: = 0-tól k-1-ig kezdődik
írjon # 40; F, ms [i, j] # 41 ;;
ha # 40; i végén;
író: # 40; F # 41 ;;
végén;

eljárás ViewNumbers # 40; k: egész szám; S: int64; V: TNumbers # 41 ;;
var i. integer;
kezdődik
írj # 40; k, ':' # 41 ;;
írjon # 40; S, ':' # 41 ;;
az i: = 0-tól k-1-ig kezdődik
írjon # 40; A [i] # 41 ;;
ha # 40; i végén;
writeln;
végén;

// Adja meg az n által k kombinációinak számát
// # 40; tekintet nélkül a 41. sorrendre;
// Cnk = n! / # 40; k! * # 40; n-k # 41 ;! # 41;
function GetCnk # 40; n, k: egész # 41 ;: int64;
var d: egész szám;
kezdődik
d: = n-k;
eredmény: = 1;
amíg n> d nem kezdődik el
eredmény: = eredmény * n;
dec # 40; n # 41 ;;
végén;
míg k> 1 megkezdődik
eredmény: = eredmény div k;
dec # 40; k # 41 ;;
végén;
végén;

function toMatrix # 40; n: egész; A: TNumbers # 41 ;: TMatrix;
var i, j: egész szám;
kezdődik
40-es betöltési karakter, 40-es méret, 41-es eredmény, 0 # 41;
az i: = 0-n-1-ig kezdődik
a j: = 0-n-1 kezdetre
eredmény [i, j]: = A [i * n + j];
végén;
végén;
végén;

// Ellenőrizze az MS-t
függvény CheckMS # 40; n: egész; m: TMatrix; var S: int64; var p, a: logikai # 41 ;: logikai;
var i, j, 11, 12. integer;
S1: egész szám;
K: int64;
kezdődik
p: = hamis;
eredmény: = true;
// Olvassa el az állandó
S: = 0;
j: = 0-n-1-ig S: = S + m [0, j];

// Ellenőrizze a sorokat
az i: = 0-n-1-ig kezdődik
S1: = 0;
j: = 0-n-1-ig S1: = S1 + m [i, j];
ha S1 <> Ekkor kezdjük
eredmény: = hamis;
exit;
végén;
végén;

// Ellenőrzés oszlopok szerint
az i: = 0-n-1-ig kezdődik
S1: = 0;
j: = 0-n-1-ig S1: = S1 + m [j, i];
ha S1 <> Ekkor kezdjük
eredmény: = hamis;
exit;
végén;
végén;

// Ellenőrizze a két átlót
S1: = 0;
j: = 0 és n-1 között S1: = S1 + m [j, j];
ha S1 <> Ekkor kezdjük
eredmény: = hamis;
exit;
végén;

S1: = 0;
j: = 0-n-1-ig S1: = S1 + m [j, n-1-j];
ha S1 <> Ekkor kezdjük
eredmény: = hamis;
exit;
végén;

// A pandiagonalitás ellenőrzése
p: = igaz;

j: = 1-től n-1-ig kezdődik
S1: = 0;
i: = 0-n-1-ig S1: = S1 + m [i, # 40; j + i # 41; mod n];
ha S1 <> Ekkor kezdjük
p: = hamis;
break;
végén;
végén;

ha p akkor kezdődik
mert j: = n - 2 * n-1 kezdődik
S1: = 0;
i: = 0-n-1-ig S1: = S1 + m [i, # 40; j-i # 41; mod n];
ha S1 <> Ekkor kezdjük
p: = hamis;
break;
végén;
végén;
végén;

// Ellenőrizze az asszociatívságot
K: = m [0.0] + m [n-1, n-1];
a: = igaz;
l1: = # 40; n-1 # 41; div 2;
az i: = 0 - l1 kezdődik
l2: = # 40; n-1 # 41; div 2;
ha n mod 2 <> 0 majd dec # 40; l2 # 41 ;;

j: = 0 - l2 kezdődik
S1: = m [i, j] + m [n-1-i, n-1-j];
ha S1 <> K kezdeni
a: = hamis;
break;
végén;
végén;
végén;
végén;

function isMagic # 40; n: egész; M: TMatrix; var S: int64; var p: logikai # 41 ;: logikai;
var i, j: egész szám;
S1: int64;
kezdődik
eredmény: = hamis;

// Számítsa ki az összeget
S: = 0;
i: = 0-n-1-ig S: = S + M [0, i];

// A karakterláncok ellenőrzése
az i: = 0-n-1-ig kezdődik
S1: = 0;
a j: = 0-n-1 kezdetre
S1: = S1 + M [i, j];
végén;
ha S1 <> S, majd kilépés;
végén;

// Ellenőrizze az oszlopokat
az i: = 0-n-1-ig kezdődik
S1: = 0;
a j: = 0-n-1 kezdetre
S1: = S1 + M [j, i];
végén;
ha S1 <> S, majd kilépés;
végén;

// Ellenőrizze a két átlót
S1: = 0;
a j: = 0-n-1 kezdetre
S1: = S1 + M [j, j];
végén;
ha S1 <> S, majd kilépés;

S1: = 0;
a j: = 0-n-1 kezdetre
S1: = S1 + M [j, n-1-j];
végén;
ha S1 <> S, majd kilépés;

p: = isPMagic # 40; n, M, S # 41 ;;
végén;

függvény isPMagic # 40; n: egész; M: TMatrix; S: int64 # 41 ;: logikai;
var k, i: egész szám;
S1. int64;
kezdődik
eredmény: = hamis;

mert k: = 0-n-1 kezdődik
S1: = 0;
az i: = 0-n-1-ig kezdődik
S1: = S1 + M [i, # 40; k + i # 41; mod n];
végén;
ha S1 <> S, majd kilépés;
végén;

mert k: = n - 2 * n-1 kezdődik
S1: = 0;
az i: = 0-n-1-ig kezdődik
S1: = S1 + M [i, # 40; k-i # 41; mod n];
végén;
ha S1 <> S, majd kilépés;
végén;

eljárás ToMatrixRosser # 40; n: egész szám; A: TNumbers; var M: TMatrix # 41 ;;
var i, j, k, l. integer;
kezdődik
az i: = 0-n-1-ig kezdődik
a j: = 0-n-1 kezdetre
k: = # 40; 3 * i + 2 * j # 41; mod n;
l: = # 40; 2 * i + j # 41; mod n;

eljárás RosserToMatrix # 40; n: egész szám; M: TMatrix; var A: TNumbers # 41 ;;
var i, j, k, l. integer;
kezdődik
az i: = 0-n-1-ig kezdődik
a j: = 0-n-1 kezdetre
k: = # 40; 3 * i + 2 * j # 41; mod n;
l: = # 40; 2 * i + j # 41; mod n;

eljárás: SetM # 40; n: egész szám; var M: TMatrix; b: az int64 # 41 ;;
var i, j: egész szám;
kezdődik
i: = 0-n-1-ig
a j: = 0-n-1 kezdetre
M [i, j]: = b [i * n + j];
végén;
végén;

eljárás: SetM # 40; n: egész szám; var M: TMatrix; b: a 41. egész szám tömbje ;;
var i, j: egész szám;
kezdődik
i: = 0-n-1-ig
a j: = 0-n-1 kezdetre
M [i, j]: = b [i * n + j];
végén;
végén;

eljárás ViewMatrix # 40; k: egész szám; V: TNumbers # 41 ;;
var i, j: egész szám;
kezdődik
az i: = 0-tól k-1-ig kezdődik
a j: = 0-tól k-1-ig kezdődik
írjon # 40; A [i * k + j], '' # 41 ;;
végén;
writeln;
végén;
végén;

// Ellenőrizze az összes mátrix számot
// true, ha minden szám különböző
függvény isDifferent # 40; n: egész; M: TMatrix # 41 ;: logikai;
var i, j, k, l, c: egész szám;
D: int64;
kezdődik
eredmény: = true;

az i: = 0-n-1-ig kezdődik
a j: = 0-n-1 kezdetre

D: = m [i, j]; c: = 0;
mert k: = 0-n-1 kezdődik
az l: = 0-n-1 kezdetre
ha m [k, l] = D, akkor kezdjük
inc # 40; c # 41 ;;
ha c> 1 akkor kezdődik
író # 40; D # 41 ;;
eredmény: = hamis;
exit;
végén;
végén;
végén;
végén;
végén;
végén;
végén;

// a -> ls
eljárás SetAInteger # 40; a: tömb egész szám; var ls: TAInteger # 41 ;;
var i: egész szám;
kezdődik
SetLength # 40; ls, high # 40; a # 41; -low # 40; a # 41; + 1 # 41 ;;
az i: = 0-tól a # 40-es hosszúságig, ls # 41-ig; - 1 ls [i]: = a [i];
végén;

Ez a program nem használ többmagos processzort.
A kérdés az, hogy lehetséges-e és milyen nehéz a teljes számítási folyamat párhuzamos bevezetését ebbe a programba?
Mint már írtam, csak két mag van a processzorban. Kollégámnak van egy négymagos processzora. Egy másik partner egyik bajtársa nyolcmagos processzorral rendelkezik, és készen áll a program végrehajtására, de nem tudja párhuzamosan készíteni a kész kódot.

Vagy talán több magot használnunk, új kódot kell írni? Az egymagos processzorra írt kód nem elégséges, nehéz vagy lehetetlen több processzoros processzorra konvertálni (?)
Ez az egész kérdés!