
Artikli tõlge on ette valmistatud kursuse üliõpilaste jaoks .
Varem rääkisin, kuidas kontrollida ja lubada Hugepages'i kasutamist Linuxis.
See artikkel on kasulik ainult juhul, kui teil on tõeliselt kusagil Hugepages'i kasutada. Olen kohtunud paljude inimestega, kes eksivad Hugepages'i kasutuse edasiviivate võimaluste üle. Siiski on hugepaging keeruline teema ja vale kasutamise korral võib see madaldada jõudlust.
Osa 1: kontrollid, et Hugepages on Linuxis lubatud (originaal )
Probleem:
Peate kontrollima, kas HugePages on teie süsteemis lubatud.
Lahendus:
See on üsna lihtne:
cat /sys/kernel/mm/transparent_hugepage/enabledKäte saad midagi sellist:
always [madvise] neverNäete saadaval olevaid valikute loetelu (always, madvise, never), millega on aktiivne valik sulgudes (vaikimisi madvise).
madvise tähendab, et transparent hugepages on lubatud ainult mälupiirkondade jaoks, mis taotlevad teadlikult hugepages'i .
always tähendab, et transparent hugepages on alati lubatud ja kõigi protsesside jaoks. See tavaliselt tõstab jõudlust, kuid kui teil on kasutusjuhtum, kus paljusid protsesse kasutavad vähe mälu, siis võib üldine mälu koormus järsult suureneda.
never tähendab, et transparent hugepages ei luba isegi siis, kui taotletakse madvise abil. Lisainformatsiooni saamiseks vaadake Linuxi kernel.
Kuidas muuta vaikeseade
Variant 1: Muutke otse sysfs (pärast taaskäivitamist naaseb seade vaikeseadele):
echo always >/sys/kernel/mm/transparent_hugepage/enabled
echo madvise >/sys/kernel/mm/transparent_hugepage/enabled
echo never >/sys/kernel/mm/transparent_hugepage/enabledOption 2: Muutke süsteemi vaikeseadeks, recompileerides kerneliga muudetud konfiguratsiooniga (see valik on soovitatav ainult juhul, kui kasutate isikupärastatud kernelit):
- Kuna vaikeseade on always, kasutage:
CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y # Kommenteeri välja CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y - Kuna vaikeseade on madvise, kasutage:
CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y # Kommenteeri välja CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
Osa 2: HugePages'i eelised ja puudused
Püüame erandlikult selgitada Hugepages'i kasutamise eeliseid, puudusi ja võimalikke vigu. Kuna tehniliselt keeruline ja pedantlik artikkel võiks olla raskesti arusaadav inimestele, kes eksivad Hugepages'i pidama imerohuks, siis ohverdan täpsuse lihtsuse nimel. Tuleb lihtsalt meeles pidada, et paljud teemad on tõeliselt keerulised ja seetõttu tohutult lihtsustatud.
Pane tähele, et räägime 64-bitistest x86 süsteemidest, mis töötavad Linuxil, ja et ma lihtsalt eeldan, et süsteem toetab läbipaistvaid hugepages'e (kuna ei ole puudus, et hugepages ei ole asendatud), nagu see juhtub praktiliselt igas kaasaegses Linuxi keskkonnas.
Allpool linkides lisan rohkem tehnilist kirjeldust.
Virtuaalne mälu
Kui oled C++ programmeerija, siis tead, et objektidel mälus on konkreetsed aadressid (pointers).
Kuid need aadressid ei pea tingimata mängima füüsilisi aadresse mälus (aadresse RAM-is). Need esindavad aadresse virtuaalses mälus. Protsessoril on spetsiaalne MMU (mäluhalduse seade), mis aitab tuumal sobitada virtuaalset mälu füüsilise asukoha juurde.
Sellisel lähenemisel on palju eeliseid, kuid kõige põhieed on:
- Tõhusus (erinevatel põhjustel);
- Programmide isoleeritus, st ükski programm ei saa lugeda teise programmi mälust.
Mis on lehed?
Virtuaalne mälu jaguneb lehtedeks. Iga eraldi leht osutab konkreetsele füüsilisele mälule, see võib viidata alale, mis on RAM-is, või aadressile, mis on määratud füüsilisele seadmele, näiteks videokaardile.
Enamik lehti, millega kokku puutute, viitab kas RAM-ile või on asendatud (swap), st salvestatud kõvakettale või SSD-le. Tuum haldab iga lehe füüsilist asukohta. Kui pääsete juurde asendatud lehele, peatab tuum voolu, mis üritab pääseda mälule, loeb lehe kõvakettalt/SSD-lt RAM-i ning seejärel jätkab voo täitmist.
See protsess on voolu jaoks läbipaistev, st see ei pea tingimata lugema otse kõvakettalt/SSD-lt. Tavaliste lehtede suurus on 4096 baiti. Hugepages'i suurus on 2 megabaiti.
Assotsiatiivne aadressitõlke vahemälu (TLB)
Kui programm pöördub mingi mälulehe poole, peab keskprotsessor teadma, milliselt füüsilise lehelt andmeid lugeda (st tal peab olema virtuaalne aadressikaart).
Tuumas on andmestruktuur (lehtede tabel), mis sisaldab kogu teavet kasutatavate lehtede kohta. Selle andmestruktuuri abil saab seostada virtuaalsed aadressid füüsiliste aadressidega.
Kahjuks on lehtede tabel üsna keeruline ja töötab aeglaselt, seega ei saa me iga kord kogu andmestruktuuri analüüsida, kui mõni protsess pöördub mälu poole.
Õnneks on meie protsessoris TLB, mis vahemällu salvestab virtuaalsete ja füüsiliste aadresside seoseid. See tähendab, et kuigi peame esmakordsel juurdepääsul lehtede tabelit analüüsima, saavad kõik järgnevate lehtedega tehtud päringud toimuda TLB kaudu, mis tagab kiire töö.
Kuna see on füüsilise seadmena rakendatud (mis teeb selle peamiselt kiireks), on selle maht piiratud. Seega, kui soovite juurde pääseda suuremale hulgale lehtedele, ei suuda TLB neid kõiki salvestada, mistõttu teie programm töötab palju aeglasemalt.
Hugepages tulevad appi.
Nii et mida saame teha, et vältida TLB ülekannet? (Eeldame, et programm vajab endiselt sama palju mälu).
Siin tulevadki mängu Hugepages. Selle asemel, et 4096 baiti vajada ainult ühte TLB kirjet, võib nüüd üks TLB kirje viidata hiiglaslikule 2 megabaidile. Eeldame, et TLB-l on 512 kirjet, siis ilma Hugepages'ita saame seostada:
4096 b⋅512=2 MBKuid nende kasutamisel võib meil seostada:
2 MB⋅512=1 GBSeetõttu on Hugepages tõeliselt ägedad. Need saavad parandada jõudlust ilma märgatava vaevata. Kuid siin on olulised tingimused.
Hugepages'i vahetus
Tuum jälgib automaatselt iga mälulehe kasutamise sagedust. Kui füüsilisest mälust (RAM) on puudu, liigutab tuum vähem olulised (harvemini kasutatavad) lehed kõvakettale, et vabastada osa RAM-i olulisemate lehtede jaoks.
Põhimõtteliselt kehtib sama ka Hugepages'i kohta. Kuid tuum saab vahetada ainult terveid lehti, mitte üksikuid baite.
Oletame, et meil on selline programm:
char* mymemory = malloc(2*1024*1024); // Võtame selle ühe Hugepage'ina!\n// Täidame mymemory mingite andmetega\n// Teeme palju muid asju,\n// mis viivad mymemory lehe vahetamiseni\n// ...\n// Taotleme juurdepääsu ainult esimesele baitile\nputchar(mymemory[0]); Sel juhul peab kernel lugema kokku 2 megabaiti teavet kõvakettalt/SSD-lt, ainult selleks, et saaksite lugeda ühte baidi. Mis puutub tavalistesse lehtedesse, siis tuleb kõvakettalt/SSD-lt lugeda vaid 4096 baiti.
Seetõttu, kui hugepage vahetatakse, toimub selle lugemine kiiremini, kuid ainult siis, kui peate juurdepääsuks lugema kogu lehte. See tähendab, et kui proovite juhuslikult pääseda erinevatele mälukohtadele ja lihtsalt loete paar kilobaiti, peaksite kasutama tavalisi lehti ja rohkem mitte muretsema.
Teisest küljest, kui peate juurdepääsu saama suurele osale mälust järjestikku, suurendavad hugepages teie tulemuslikkust. Siiski peate selle ise kontrollima (mitte abstraktse tarkvara põhjal) ja vaatama, mis töötab kiiremini.
Mälu allokatsioon
Kui kirjutate C-s, teate, et saate taotleda niivõrd väikseid (või peaaegu nii suuri) mälu hulki, kui soovite, kasutades malloc(). Oletame, et vajate 30 baiti mälu:
char* mymemory = malloc(30);Arendajale võib tunduda, et te "taotlete" 30 baiti mälu operatsioonisüsteemist ja tagastate pointeri mingisse virtuaalsesse mällu. Kuid tegelikult malloc () on lihtsalt C funktsioon, mis kutsub seespool välja funktsioonid operatsioonisüsteemist mälu taotlemiseks või vabastamiseks.
Kuid üha rohkem mälu taotlemine iga allokatsiooni jaoks ei ole efektiivne; on tõenäolisem, et mõni mälu segment on juba vabastatud (free()), ja me saame seda taas kasutada. malloc() rakendab üsna keerulisi algoritme vabastatud mälu taaskasutamiseks.
Samal ajal toimub see kõik teie jaoks märkamatult, nii et miks peaks see teid muretsema? Aga see on sellepärast, et kutsumine free() ei tähenda, et .
On olemas selline mõisted nagu mälu fragmenteerumine. Äärmuslikel juhtudel on hunniku segmendid, kus kasutatakse vaid mõnda baiti, samas kui kõik, mis nende vahel, on vabastatud. (free()).
Pange tähele, et mälu fragmenteerumine on äärmiselt keeruline teema ning isegi vähesed muudatused programmis võivad sellele märkimisväärselt mõjuda. Enamikul juhtudel ei põhjusta programmid märkimisväärset mälu fragmenteerumist, kuid peate meeles pidama, et kui mõnes hunniku piirkonnas on fragmenteerumise probleem, võivad hugepages olukorda halvendada.
Valikuline hugepages rakendamine
Pärast artikli lugemist olete kindlaks teinud, millised teie programmi osad saavad hugepages'i rakendamisest kasu ja millised mitte. Nii et kas on mõtet hugepages sisse lülitada?
Õnneks saate kasutada madvise(), et lubada hugepaging ainult nende mälu piirkondade puhul, kus see on kasulik.
Alustuseks kontrollige, et hugepages töötavad madvise() režiimis, kasutades artikli alguses.
Seejärel kasutage madvise(), et öelda tuumas, kus täpselt hugepages'i kasutada.
#include <sys/mman.h>
// Аллоцируйте большое количество памяти, которую будете использовать
size_t size = 256*1024*1024;
char* mymemory = malloc(size);
// Просто включите hugepages…
madvise(mymemory, size, MADV_HUGEPAGE);
// … и задайте следующее
madvise(mymemory, size, MADV_HUGEPAGE | MADV_SEQUENTIAL)Pange tähele, et see meetod on lihtsalt soovitus tuumale mälu haldamiseks. See ei tähenda, et tuum automaatselt kasutab hugepages'i antud mälu jaoks.
Tutvuge dokumentatsiooniga , et rohkem teada saada mälu haldamisest ja madvise(), selle teema õppimiskurss on uskumatult järsk. Seetõttu, kui kavatsete tõeliselt hästi aru saada, valmistuge lugema ja testima nädalaid, enne kui loote lootust mingite positiivsete tulemuste saamiseks.
Mida lugeda?
Küsimus? Kirjutage kommentaaridesse!
Allikas: habr.com
