Programavimas

Kodėl efektyvus lygiagretus programavimas turi apimti kintamos atminties paskirstymą

Daugiagyslis procesorius? Taip.

Parašyti programą, kad ji veiktų lygiagrečiai? Taip.

Ar nepamiršote naudoti „Scalable Memory Allocator“? Ne? Tada skaitykite toliau ...

Mano patirtis rodo, kad programos „atminties paskirstymas“ yra paruoštas lygiagretumui, dažnai nepastebimas elementas, kad lygiagreti programa veiktų gerai. Galiu parodyti neįtikėtinai paprastą būdą sužinoti, ar tai yra kompiliuojamos programos problema (C, C ++, Fortran ir kt.), Ir kaip ją išspręsti.

Kritinė bet kurios lygiagrečios programos dalis yra keičiamo dydžio atminties paskirstymas, kuris apima programos naudojimąnaujastaip pat aiškūs skambučiaimalloc, calloc arba realloc. Pasirinktys yra „TBBmalloc“ („Intel Threading Building Blocks“), „jemalloc“ ir „tcmalloc“. „TBBmalloc“ turi naują „tarpinio serverio“ funkciją, kurią naudojant bet kurią sukompiliuotą programą lengva išbandyti mažiau nei per 5 minutes.

Nemažos naudos, susijusios su keičiamo dydžio atminties paskirstytoju, naudai. „TBBmalloc“ buvo vienas iš pirmųjų plačiai naudojamų keičiamo dydžio atminties paskirstytojų, nemenkai todėl, kad jis turėjo nemokamą TBB, kad padėtų pabrėžti atminties paskirstymo svarbos įtraukimo į bet kurią lygiagrečią programą svarbą. Jis išlieka nepaprastai populiarus ir vis dar yra vienas iš geriausių prieinamų atminties paskirstytojų.

Lengvas sprendimas be kodo pakeitimų

Naudodami tarpinius metodus galime pakeisti visame pasaulyje naujas/Ištrinti ir malloc/kalok/realloc/Laisvas/ ir kt. rutinos su dinaminės atminties sąsajos pakeitimo technika. Šis automatinis būdas pakeisti numatytąsias dinaminės atminties paskirstymo funkcijas yra pats populiariausias būdas naudoti „TBBmalloc“. Tai lengva ir pakanka daugumai programų.

Kiekvienoje operacinėje sistemoje naudojamo mechanizmo detalės šiek tiek skiriasi, tačiau grynasis poveikis visur yra vienodas.

5 minučių bandymą pradedame atsisiųsdami ir įdiegdami „Threading Building Blocks“ (be //threadingbuildingblocks.org; jis taip pat įtrauktas kaip „Intel Parallel Studio“ produktų dalis).

„Linux“ naudokite tarpinį serverį

„Linux“ sistemoje pakeitimą galime atlikti įkeldami tarpinio serverio biblioteką programos įkėlimo metu naudodami LD_PRELOAD aplinkos kintamasis (nekeičiant vykdomojo failo) arba susiejant pagrindinį vykdomąjį failą su tarpinio serverio biblioteka (-ltbbmalloc_proxy). „Linux“ programos krautuvas turi sugebėti rasti tarpinę biblioteką ir keičiamo dydžio atminties paskirstymo biblioteką programos įkėlimo metu. Tam mes galime įtraukti katalogą, kuriame yra bibliotekos, į LD_LIBRARY_PATH aplinkos kintamąjį arba pridėkite jį prie /etc/ld.so.conf.

Pabandykite taip:

laikas ./a.out (ar kaip vadinasi mūsų programa)

eksportuoti LD_PRELOAD = libtbbmalloc_proxy.so.2

laikas ./a.out (ar kaip vadinasi mūsų programa)

„MacOS“ naudokite tarpinį serverį

„MacOS“ sistemoje pakeitimą galime atlikti įkeldami tarpinio serverio biblioteką programos įkėlimo metu naudodami DYLD_INSERT_LIBRARIES aplinkos kintamasis (nekeičiant vykdomojo failo) arba susiejant pagrindinį vykdomąjį failą su tarpinio serverio biblioteka (-ltbbmalloc_proxy). „MacOS“ programos krautuvas turi sugebėti rasti tarpinę biblioteką ir keičiamo dydžio atminties paskirstymo biblioteką programos įkėlimo metu. Tam galime įtraukti katalogą, kuriame yra bibliotekos, į DYLD_LIBRARY_PATH aplinkos kintamasis.

Pabandykite taip:

laikas ./a.out (ar kaip pavadintume mūsų programą)

eksportuoti DYLD_INSERT_LIBRARIES = $ TBBROOT / lib / libtbbmalloc_proxy.dylib

laikas ./a.out (ar kaip pavadintume mūsų programą)

„Windows“ naudokite tarpinį serverį

„Windows“ sistemoje turime modifikuoti vykdomąjį failą. Mes galime priversti įkelti tarpinio serverio biblioteką pridedant #include "tbb / tbbmalloc_proxy.h" šaltinio kode arba naudojant tam tikras susiejimo parinktis kuriant vykdomąjį failą:

„Win32“:

            tbbmalloc_proxy.lib / ĮSKAIČIUOTI: "___ TBB_malloc_proxy"

„Win64“:

            tbbmalloc_proxy.lib / ĮSKAIČIUOTI: "__ TBB_malloc_proxy"

„Windows“ programos krautuvas turi įgalinti rasti tarpinę biblioteką ir keičiamo dydžio atminties paskirstymo biblioteką programos įkėlimo metu. Tam mes galime įtraukti katalogą, kuriame yra bibliotekos, į KELIS aplinkos kintamasis. Išbandykite naudodamiesi „Visual Studio“ „Performance Profiler“, kad programa būtų suplanuota su įtraukimo ar susiejimo parinktimi ir be jos.

Mūsų tarpinio bibliotekos naudojimo testavimas naudojant mažą programą

Aš raginu jus išbandyti savo programą, kaip aprašyta aukščiau. Paleiskite su tarpiniu serveriu ir be jo ir sužinokite, kiek naudos gauna jūsų programa. Programos, kuriose yra daug paralelizmo ir daug atminties paskirstymo, dažnai mato 10–20% padidėjimą (kartą taip pat mačiau 400% padidėjimą), tuo tarpu programos, turinčios mažai paralelizmo ar mažai paskirstymų, gali visiškai nepastebėti. Greiti testai, aprašyti anksčiau, su tarpinio serverio biblioteka parodys, kurioje kategorijoje yra jūsų programa.

Aš taip pat parašiau trumpą programą, kad iliustruočiau efektus ir pateikčiau paprastą būdą patikrinti, ar viskas įdiegta ir veikia taip, kaip tikėtasi. Mes galime išbandyti tarpinę biblioteką naudodami paprastą programą:

# įtraukti

#include „tbb / tbb.h“

naudojant vardų srities tbb;

const int N = 1000000;

int main () {

dvigubas * a [N];

parallel_for (0, N-1, [&] (int i) {a [i] = naujas dvigubas;});

parallel_for (0, N-1, [&] (int i) {ištrinti a [i];});

grąžinti 0;

}

Mano pavyzdinė programa naudoja daug vietos kamino, todėl „ulimit - neribotas“(„ Linux “/„ macOS “) arba„/ ŠUOLA: 10000000“(„ Visual Studio “: Ypatybės> Sąrankos ypatybės>„ Linker “>„ System “>„ Stack Reserve Size “) bus svarbu, kad išvengtumėte neatidėliotinų gedimų.

Po kompiliavimo pateikiami įvairūs būdai, kaip paleidžiau savo mažą programą, kad galėčiau pamatyti greitį su tarpinio serverio biblioteka ir be jos.

Bėgimas ir laikas tbb_mem.cpp quadcore virtualus „Linux“ mašina, pamačiau:

% laiko ./tbb_mem

tikras 0m0.160s

vartotojas 0m0.072s

sys 0m0.048s

%

% exportLD_PRELOAD = $ TBBROOT / lib / libtbbmalloc_proxy.dylib

%

% laiko ./tbb_mem

tikras 0m0,043s

vartotojas 0m0.048s

sys 0m0.028s

Vykdydamas ir planuodamas „tbb_mem.cpp“ „quadcore iMac“ („MacOS“), pamačiau:

% laiko ./tbb_mem

tikras 0m0,046s

vartotojas 0m0.078s

sys 0m0.053s

%

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

%

% laiko ./tbb_mem

tikras 0m0,019s

vartotojas 0m0.032s

sys 0m0.009s

Sistemoje „Windows“, naudodamas „Visual Studio“ „Performance Profiler“, „quadcore Intel NUC“ („Core i7“), pamačiau 94 ms be keičiamo atminties profilio ir 50 ms kartų (pridedant #include "tbb / tbbmalloc_proxy.h"į pavyzdinę programą).

Kompiliavimo svarstymai

Asmeniškai aš neturėjau problemų dėl kompiliatorių, atliekančių „malloc optimizavimą“, bet techniškai siūlyčiau, kad kompiliuojant su programomis, tokius kompiliatorių „malloc optimizavimus“ reikėtų išjungti. Gali būti protinga patikrinti mėgstamiausio kompiliatoriaus kompiliatoriaus dokumentaciją. Pvz., Naudojant „Intel“ kompiliatorius arba „gcc“, geriausia perduoti šias vėliavas:

-fno-builtin-malloc („Windows“: / Qfno-builtin-malloc)

-fno-builtin-calloc („Windows“: / Qfno-builtin-calloc)

-fno-builtin-realloc („Windows“: / Qfno-builtin-realloc)

-fno-builtin-free („Windows“: / Qfno-builtin-free)

Nenaudojant šių žymių problema gali nekilti, tačiau nėra bloga mintis būti saugiam.

Santrauka

Keičiamos atminties paskirstytuvo naudojimas yra būtinas bet kurios lygiagrečios programos elementas. Parodžiau, kad TBBmalloc galima lengvai įšvirkšti nereikalaujant kodo keitimo (nors mano mėgstamiausias „Windows“ sprendimas pridėti „įtraukti“ sistemoje „Windows“). Galite pamatyti puikų greitį, atlikdami tik 5 minutes darbo, ir galite lengvai pritaikyti jį kelioms programoms. „Linux“ ir „MacOS“ sistemose galbūt net galėsite pagreitinti programas neturėdami šaltinio kodo!

Spustelėkite čia norėdami atsisiųsti nemokamą 30 dienų „Intel Parallel Studio XE“ bandomąją versiją.

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