Programiranje

Zakaj mora učinkovito vzporedno programiranje vključevati razširljivo dodeljevanje pomnilnika

Večjedrni procesor? Da.

Napišite program za vzporedni zagon? Da.

Ste se spomnili uporabiti razširljiv pomnilnik za pomnilnik? Ne? Nato beri naprej ...

Po mojih izkušnjah je zagotovitev, da je »dodelitev pomnilnika« za program pripravljena na vzporednost, pogosto spregledan element dobrega delovanja vzporednega programa. Lahko vam pokažem neverjetno enostaven način, kako ugotoviti, ali to predstavlja težavo za prevedeni program (C, C ++, Fortran itd.), Pa tudi kako to popraviti.

Ključni del katerega koli vzporednega programa je razširljiva dodelitev pomnilnika, ki vključuje uporabonovopa tudi izrecne klicemalloc, calloc ali realloc. Možnosti vključujejo TBBmalloc (gradniki Intel Threading Building Blocks), jemalloc in tcmalloc. TBBmalloc ima novo funkcijo "proxy", ki olajša poskus v manj kot 5 minutah katerega koli sestavljenega programa.

Prednosti uporabe razširljivega razdeljevalnika pomnilnika so velike. TBBmalloc je bil med prvimi pogosto uporabljivimi razširljivimi razdeljevalci pomnilnika, v majhnem delu, ker je s TBB na voljo brezplačno, da bi poudaril pomembnost vključitve premislekov o dodeljevanju pomnilnika v kateri koli vzporedni program. Danes ostaja izjemno priljubljen in je še vedno eden najboljših razširljivih razdeljevalcev pomnilnika, ki so na voljo.

Preprosta rešitev brez sprememb kode

Z uporabo metod proxy lahko globalno nadomestimo novo/izbriši in malloc/calloc/realloc/prost/ itd. rutine s tehniko nadomestitve dinamičnega pomnilniškega vmesnika. Ta samodejni način zamenjave privzetih funkcij za dinamično dodeljevanje pomnilnika je daleč najbolj priljubljen način uporabe TBBmalloc. Za večino programov je enostavno in dovolj.

Podrobnosti mehanizma, ki se uporablja v vsakem operacijskem sistemu, se nekoliko razlikujejo, vendar je neto učinek povsod enak.

Naš 5-minutni preskus začnemo s prenosom in namestitvijo Threading Building Blocks (brez //threadingbuildingblocks.org; vključen je tudi kot del izdelkov Intel Parallel Studio).

Uporabite proxy v Linuxu

V Linuxu lahko nadomestimo bodisi z nalaganjem knjižnice proxy ob nalaganju programa s pomočjo LD_PRELOAD spremenljivko okolja (brez spreminjanja izvršljive datoteke) ali s povezovanjem glavne izvršljive datoteke s knjižnico proxy (-ltbbmalloc_proxy). Nalagalnik programov Linux mora biti sposoben najti knjižnico proxy in razširljivo knjižnico za razdeljevanje pomnilnika v času nalaganja programa. Za to lahko vključimo imenik, ki vsebuje knjižnice v LD_LIBRARY_PATH spremenljivko okolja ali jo dodajte v /etc/ld.so.conf.

Poskusite na naslednji način:

čas ./a.out (ali kakorkoli se imenuje naš program)

izvoz LD_PRELOAD = libtbbmalloc_proxy.so.2

čas ./a.out (ali kakorkoli se imenuje naš program)

Uporabite proxy za macOS

V macOS lahko nadomestimo bodisi z nalaganjem knjižnice proxy ob nalaganju programa s pomočjo DYLD_INSERT_LIBRARIES spremenljivko okolja (brez spreminjanja izvršljive datoteke) ali s povezovanjem glavne izvršljive datoteke s knjižnico proxy (-ltbbmalloc_proxy). Nalagalnik programov macOS mora biti sposoben najti knjižnico proxy in razširljivo knjižnico za razdeljevanje pomnilnika v času nalaganja programa. Za to lahko vključimo imenik, ki vsebuje knjižnice v DYLD_LIBRARY_PATH spremenljivka okolja.

Poskusite na naslednji način:

čas ./a.out (ali kakorkoli se imenuje naš program)

izvoz DYLD_INSERT_LIBRARIES = $ TBBROOT / lib / libtbbmalloc_proxy.dylib

čas ./a.out (ali kakorkoli se imenuje naš program)

Uporabite proxy v sistemu Windows

V sistemu Windows moramo spremeniti svojo izvedljivo datoteko. Knjižnico proxy lahko prisilno naložimo tako, da dodamo #include "tbb / tbbmalloc_proxy.h" v naši izvorni kodi ali z uporabo nekaterih povezovalnih možnosti pri gradnji izvršljive datoteke:

Za win32:

            tbbmalloc_proxy.lib / INCLUDE: "___ TBB_malloc_proxy"

Za win64:

            tbbmalloc_proxy.lib / INCLUDE: "__ TBB_malloc_proxy"

Nalagalnik programov Windows mora biti sposoben najti knjižnico proxy in razširljivo knjižnico za razdeljevanje pomnilnika v času nalaganja programa. Za to lahko vključimo imenik, ki vsebuje knjižnice v POT spremenljivka okolja. Preizkusite ga tako, da uporabite Visual Studio »Performance Profiler«, da časovite program z in brez možnosti vključitve ali povezave.

Testiranje uporabe proxy knjižnice z majhnim programom

Priporočam vam, da poskusite z lastnim programom, kot je opisano zgoraj. Zaženite s proxyjem in brez njega ter preverite, koliko koristi ima vaša aplikacija. Aplikacije z veliko vzporednosti in veliko dodeljenimi pomnilniki pogosto opazijo 10–20% povišanj (tudi enkrat sem jih že povišala za 400%), medtem ko programi z malo vzporednosti ali z malo dodelitvami morda nimajo nobenega učinka. Prej opisani hitri testi s knjižnico proxy vam bodo povedali, v katero kategorijo spada vaša aplikacija.

Napisal sem tudi kratek program za ponazoritev učinkov in enostaven način preverjanja, ali so stvari nameščene in delujejo po pričakovanjih. Knjižnico proxy lahko preizkusimo s preprostim programom:

#include

#include "tbb / tbb.h"

uporaba imenskega prostora tbb;

const int N = 1000000;

int main () {

dvojno * a [N];

vzporedno_za (0, N-1, [&] (int i) {a [i] = novo dvojno;});

vzporedno_za (0, N-1, [&] (int i) {izbriši [i];});

vrnitev 0;

}

Moj primer programa uporablja veliko prostora za sklad, zato "ulimit - neomejeno"(Linux / macOS) ali"/ ZLOG: 10000000«(Visual Studio: Lastnosti> Konfiguracijske lastnosti> Povezovalnik> Sistem> Velikost rezerve sklada) bo pomemben, da se izognete takojšnjim zrušitvam.

Po prevajanju so tukaj različni načini, kako sem zagnal svoj mali program, da vidim hitrost z in brez knjižnice proxy.

Zagon in merjenje časa tbb_mem.cpp na štirikotniku virtualni Na računalniku Linux sem videl naslednje:

% čas ./tbb_mem

realne 0m0.160s

uporabnik 0m0.072s

sys 0m0.048s

%

% exportLD_PRELOAD = $ TBBROOT / lib / libtbbmalloc_proxy.dylib

%

% čas ./tbb_mem

realne 0m0.043s

uporabnik 0m0.048s

sys 0m0.028s

Med izvajanjem in določanjem časa tbb_mem.cpp na quadcore iMac (macOS) sem videl naslednje:

% čas ./tbb_mem

realne 0m0.046s

uporabnik 0m0.078s

sys 0m0.053s

%

% export DYLD_INSERT_LIBRARIES = $ TBBROOT / lib / libtbbmalloc_proxy.dylib

%

% čas ./tbb_mem

realne 0m0.019s

uporabnik 0m0.032s

sys 0m0.009s

V operacijskem sistemu Windows sem z uporabo Visual Studio “Performance Profiler” na quadcore Intel NUC (Core i7) videl čas 94 ms brez razširljivega pomnilniškega profilatorja in 50 ms z njim (dodajanje #include "tbb / tbbmalloc_proxy.h"v primer programa).

Premisleki o kompilaciji

Osebno nisem imel težav s prevajalniki, ki izvajajo »malloc optimizacije«, vendar bi tehnično predlagal, da bi pri prevajanju programov onemogočili takšne »preoblikovalnike malloc«. Morda bi bilo pametno preveriti dokumentacijo prevajalnika vašega najljubšega prevajalnika. Na primer, pri Intelovih prevajalnikih ali gcc je najbolje, da navedete naslednje zastavice:

-fno-builtin-malloc (v sistemu Windows: / Qfno-builtin-malloc)

-fno-builtin-calloc (v sistemu Windows: / Qfno-builtin-calloc)

-fno-builtin-realloc (v sistemu Windows: / Qfno-builtin-realloc)

-fno-vgrajeno brez (v sistemu Windows: / Qfno-vgrajeno brez)

Če teh zastavic ne uporabite, morda ne bo povzročala težav, vendar ni slabo, če ste varni.

Povzetek

Uporaba razširljivega razdeljevalnika pomnilnika je bistven element katerega koli vzporednega programa. Pokazal sem, da je TBBmalloc mogoče enostavno vbrizgati, ne da bi bilo treba spremeniti kodo (čeprav je dodajanje "vključi" v Windows moja najljubša rešitev za Windows). Morda boste opazili lepo pospešitev s samo 5 minutami dela in jo lahko enostavno uporabite za več aplikacij. V Linuxu in macOS boste morda lahko celo pospešili programe, ne da bi imeli izvorno kodo!

Kliknite tukaj, če želite prenesti brezplačno 30-dnevno preskusno različico Intel Parallel Studio XE.

$config[zx-auto] not found$config[zx-overlay] not found