Դասընթացի ուսանողների համար պատրաստված հոդվածի թարգմանությունը «Linux Administrator».
Նախկինում ես խոսեցի այն մասին, թե ինչպես փորձարկել և միացնել Hugepages-ը Linux-ում:
Այս հոդվածը օգտակար կլինի միայն այն դեպքում, եթե դուք իսկապես տեղ ունեք Hugepages-ից օգտվելու համար: Ես հանդիպել եմ շատ մարդկանց, ովքեր խաբված են այն հեռանկարով, որ Hugepages-ը կախարդական կերպով կբարելավի արտադրողականությունը: Այնուամենայնիվ, հսկայական էջերը բարդ թեմա է և կարող է վատթարացնել կատարողականությունը, եթե սխալ օգտագործվի:
Մաս 1. Ստուգում, որ հսկայական էջերը միացված են Linux-ում (օրիգինալ այստեղ)
Problem:
Դուք պետք է ստուգեք, արդյոք HugePages-ը միացված է ձեր համակարգում:
լուծում:
Դա բավականին պարզ է.
cat /sys/kernel/mm/transparent_hugepage/enabled
Դուք կստանաք նման բան.
always [madvise] never
Դուք կտեսնեք առկա ընտրանքների ցանկը (միշտ, խելագար, երբեք), իսկ ներկայումս ակտիվ տարբերակը կփակվի փակագծերում (ըստ լռելյայն խենթացնել).
խենթացնել նշանակում է, որ transparent hugepages միացված է միայն հիշողության տարածքների համար, որոնք բացահայտորեն պահանջում են հսկայական էջեր օգտագործելով խելագարություն (2).
միշտ նշանակում է, որ transparent hugepages միշտ միացված է բոլոր գործընթացների համար: Սա սովորաբար բարելավում է կատարումը, բայց եթե դուք ունեք օգտագործման դեպք, երբ շատ գործընթացներ սպառում են փոքր քանակությամբ հիշողություն, ապա ընդհանուր հիշողության ծանրաբեռնվածությունը կարող է կտրուկ աճել:
երբեք նշանակում է, որ transparent hugepages չի ներառվի նույնիսկ այն դեպքում, երբ պահանջվում է օգտագործելով madvise: Ավելին իմանալու համար դիմեք փաստաթղթավորում Linux միջուկներ.
Ինչպես փոխել լռելյայն արժեքը
Ընտրանք 1Անմիջապես փոխել sysfs (վերագործարկումից հետո պարամետրը կվերադառնա իր լռելյայն արժեքին).
echo always >/sys/kernel/mm/transparent_hugepage/enabled
echo madvise >/sys/kernel/mm/transparent_hugepage/enabled
echo never >/sys/kernel/mm/transparent_hugepage/enabled
Ընտրանք 2Փոխեք համակարգի լռելյայնությունը՝ վերակոմպիլացնելով միջուկը փոփոխված կազմաձևով (այս տարբերակը խորհուրդ է տրվում միայն այն դեպքում, եթե դուք օգտագործում եք հատուկ միջուկ):
Միշտ լռելյայն սահմանելու համար օգտագործեք՝
CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
# Comment out CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
Madvise-ը որպես լռելյայն սահմանելու համար օգտագործեք՝
CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
# Comment out CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
Մաս 2. HugePages-ի առավելություններն ու թերությունները
Մենք կփորձենք ընտրողաբար բացատրել Hugepages-ի օգտագործման առավելությունները, թերությունները և հնարավոր թակարդները: Քանի որ տեխնոլոգիապես բարդ և մանկական հոդվածը, հավանաբար, դժվար կլինի հասկանալ այն մարդկանց համար, ովքեր մոլորության մեջ են, որ Hugepages-ը համադարման միջոց է, ես կզոհաբերեմ ճշգրտությունը պարզության համար: Պարզապես արժե նկատի ունենալ, որ շատ թեմաներ իսկապես բարդ են և, հետևաբար, շատ պարզեցված:
Խնդրում ենք նկատի ունենալ, որ մենք խոսում ենք Linux-ով աշխատող 64-բիթանոց x86 համակարգերի մասին, և որ ես պարզապես ենթադրում եմ, որ համակարգը աջակցում է թափանցիկ հսկայական էջեր (քանի որ թերություն չէ, որ հսկայական էջերը չեն վերագրվում), ինչպես դա տեղի է ունենում գրեթե ցանկացած ժամանակակից Linux-ում: միջավայրը։
Ես կցեմ ավելի շատ տեխնիկական նկարագրություն ստորև բերված հղումներում:
Վիրտուալ հիշողություն
Եթե դուք C++ ծրագրավորող եք, գիտեք, որ հիշողության մեջ գտնվող օբյեկտներն ունեն հատուկ հասցեներ (ցուցիչի արժեքներ):
Այնուամենայնիվ, այս հասցեները պարտադիր չէ, որ արտացոլեն ֆիզիկական հասցեները հիշողության մեջ (RAM հասցեներ): Նրանք ներկայացնում են հասցեներ վիրտուալ հիշողության մեջ: Պրոցեսորն ունի հատուկ MMU (հիշողության կառավարման միավոր) մոդուլ, որն օգնում է միջուկին վիրտուալ հիշողությունը քարտեզագրել ֆիզիկական վայրում:
Այս մոտեցումը շատ առավելություններ ունի, բայց ամենակարևորներն են.
Կատարում (տարբեր պատճառներով);
Ծրագրի մեկուսացում, այսինքն՝ ոչ մի ծրագիր չի կարող կարդալ մեկ այլ ծրագրի հիշողությունից։
Ի՞նչ են էջերը:
Վիրտուալ հիշողությունը բաժանված է էջերի։ Յուրաքանչյուր առանձին էջ մատնանշում է որոշակի ֆիզիկական հիշողություն, այն կարող է մատնանշել RAM-ի տարածքը կամ կարող է մատնանշել ֆիզիկական սարքին հատկացված հասցե, օրինակ՝ վիդեո քարտ:
Էջերի մեծ մասը, որոնց հետ գործ ունեք, կա՛մ մատնանշում են RAM-ը, կա՛մ փոխվում են, այսինքն՝ դրանք պահվում են ձեր կոշտ սկավառակի կամ SSD-ի վրա: Միջուկը կառավարում է յուրաքանչյուր էջի ֆիզիկական դասավորությունը: Եթե կեղծված էջ մուտք է գործում, միջուկը դադարեցնում է շարանը, որը փորձում է մուտք գործել հիշողություն, կարդում է էջը կոշտ սկավառակից/SSD-ից դեպի RAM և այնուհետև շարունակում է գործարկել շարանը:
Այս գործընթացը հոսքային թափանցիկ է, ինչը նշանակում է, որ այն պարտադիր չէ, որ կարդալ անմիջապես HDD/SSD-ից: Նորմալ էջերի չափը 4096 բայթ է։ Հսկայական էջերի չափը 2 մեգաբայթ է:
Թարգմանական ասոցիատիվ բուֆեր (TLB)
Երբ ծրագիրը մուտք է գործում հիշողության էջ, պրոցեսորը պետք է իմանա, թե որ ֆիզիկական էջից պետք է կարդալ տվյալները (այսինքն ունենալ վիրտուալ հասցեի քարտեզ):
Միջուկն ունի տվյալների կառուցվածք (էջ աղյուսակ), որը պարունակում է օգտագործվող էջերի մասին ամբողջ տեղեկատվությունը: Օգտագործելով այս տվյալների կառուցվածքը, կարող եք վիրտուալ հասցեն ֆիզիկական հասցեի քարտեզագրել:
Այնուամենայնիվ, էջերի աղյուսակը բավականին բարդ և դանդաղ է, ուստի մենք պարզապես չենք կարող վերլուծել տվյալների ամբողջ կառուցվածքը ամեն անգամ, երբ գործընթացը մուտք է գործում հիշողություն:
Բարեբախտաբար, մեր պրոցեսորն ունի TLB, որը պահում է քարտեզագրումը վիրտուալ և ֆիզիկական հասցեների միջև: Սա նշանակում է, որ չնայած մենք պետք է վերլուծենք էջի աղյուսակը առաջին մուտքի փորձի ժամանակ, էջին հաջորդող բոլոր մուտքերը կարող են կարգավորվել TLB-ում, ինչը թույլ է տալիս արագ գործել:
Քանի որ այն ներդրված է որպես ֆիզիկական սարք (ինչն առաջին հերթին արագացնում է), դրա հզորությունը սահմանափակ է: Այսպիսով, եթե ցանկանում եք մուտք գործել ավելի շատ էջեր, TLB-ն չի կարողանա բոլորի համար քարտեզներ պահել, ինչի պատճառով ձեր ծրագիրը շատ ավելի դանդաղ է աշխատում:
Օգնության է գալիս Hugepages-ը
Այսպիսով, ի՞նչ կարող ենք անել TLB-ի արտահոսքից խուսափելու համար: (Մենք ենթադրում ենք, որ ծրագիրը դեռևս նույն քանակությամբ հիշողության կարիք ունի):
Հենց այստեղ է գալիս Hugepages-ը: 4096 բայթի փոխարեն, որը պահանջում է ընդամենը մեկ TLB մուտք, մեկ TLB մուտքն այժմ կարող է ցույց տալ հսկայական 2 մեգաբայթ: Ենթադրենք, որ TLB-ն ունի 512 գրառում, այստեղ առանց Hugepages մենք կարող ենք համապատասխանել.
4096 b⋅512=2 MB
Այդ դեպքում ինչպես կարող ենք համեմատվել նրանց հետ.
2 MB⋅512=1 GB
Ահա թե ինչու է Hugepages-ը հիանալի: Նրանք կարող են բարելավել արտադրողականությունը առանց մեծ ջանքերի: Բայց այստեղ զգալի նախազգուշացումներ կան:
Հսկայական էջերի կեղծում
Միջուկը ավտոմատ կերպով վերահսկում է, թե որքան հաճախ է օգտագործվում յուրաքանչյուր հիշողության էջը: Եթե բավարար ֆիզիկական հիշողություն (RAM) չկա, միջուկը ավելի քիչ կարևոր (ավելի քիչ հաճախ օգտագործվող) էջերը կտեղափոխի կոշտ սկավառակ՝ ավելի կարևոր էջերի համար որոշ RAM ազատելու համար:
Սկզբունքորեն նույնը վերաբերում է Hugepages-ին։ Այնուամենայնիվ, միջուկը կարող է փոխանակել միայն ամբողջ էջերը, այլ ոչ թե առանձին բայթեր:
Եկեք ասենք, որ մենք ունենք այսպիսի ծրագիր.
char* mymemory = malloc(2*1024*1024); // Возьмем это за одну Hugepage!
// Заполним mymemory какими-либо данными
// Сделаем много других вещей,
// которые приведут к подмене страницы mymemory
// ...
// Запросим доступ только к первому байту
putchar(mymemory[0]);
Այս դեպքում միջուկը պետք է փոխարինի (կարդա) մինչև 2 մեգաբայթ տեղեկատվություն կոշտ սկավառակից/SSD-ից միայն մեկ բայթ կարդալու համար: Ինչ վերաբերում է սովորական էջերին, ապա կոշտ սկավառակից/SSD-ից անհրաժեշտ է կարդալ ընդամենը 4096 բայթ:
Հետևաբար, եթե հսկայական էջը վերացված է, այն ավելի արագ է կարդալ միայն այն դեպքում, եթե ձեզ անհրաժեշտ է մուտք գործել ամբողջ էջ: Սա նշանակում է, որ եթե դուք փորձում եք պատահականորեն մուտք գործել հիշողության տարբեր մասեր և պարզապես կարդում եք մի քանի կիլոբայթ, ապա պետք է օգտագործեք սովորական էջեր և չանհանգստանաք այլ բանի համար:
Մյուս կողմից, եթե ձեզ անհրաժեշտ է հաջորդաբար մուտք գործել հիշողության մեծ մասը, հսկայական էջերը կբարելավեն ձեր կատարումը: Այնուամենայնիվ, դուք պետք է փորձարկեք այն ինքներդ (ոչ վերացական ծրագրաշարով) և տեսնեք, թե ինչն է ավելի արագ աշխատում:
Հիշողության մեջ տեղաբաշխում
Եթե գրում եք C, դուք գիտեք, որ դուք կարող եք կամայականորեն փոքր (կամ գրեթե կամայականորեն մեծ) հիշողություն պահանջել կույտից՝ օգտագործելով malloc(). Ենթադրենք, ձեզ անհրաժեշտ է 30 բայթ հիշողություն.
char* mymemory = malloc(30);
Ծրագրավորողին կարող է թվալ, որ դուք օպերացիոն համակարգից «պահանջում եք» 30 բայթ հիշողություն և ցուցիչ եք վերադարձնում որոշ վիրտուալ հիշողություն: Բայց իրականում malloc () պարզապես C ֆունկցիա է, որը կանչում է ֆունկցիայի ներսից բրկ և սբրկ օպերացիոն համակարգից հիշողություն պահանջելու կամ ազատելու համար:
Այնուամենայնիվ, յուրաքանչյուր տեղաբաշխման համար ավելի ու ավելի շատ հիշողություն պահանջելը անարդյունավետ է. Ամենայն հավանականությամբ, հիշողության որոշ հատված արդեն ազատվել է (free()), և մենք կարող ենք նորից օգտագործել այն: malloc() իրականացնում է բավականին բարդ ալգորիթմներ ազատված հիշողության վերօգտագործման համար:
Կա հիշողության մասնատվածություն: Ծայրահեղ դեպքերում կան կույտային հատվածներ, որտեղ օգտագործվում են ընդամենը մի քանի բայթ, մինչդեռ միջև եղած ամեն ինչ ազատվել է (free()).
Խնդրում ենք նկատի ունենալ, որ հիշողության մասնատումը աներևակայելի բարդ թեմա է, և նույնիսկ ծրագրի աննշան փոփոխությունները կարող են զգալի ազդեցություն ունենալ: Շատ դեպքերում ծրագրերը չեն առաջացնի հիշողության զգալի մասնատում, բայց դուք պետք է տեղյակ լինեք, որ եթե կույտի որոշ հատվածում մասնատման խնդիր կա, հսկայական էջերը կարող են վատթարացնել իրավիճակը:
Հսկայական էջերի ընտրովի օգտագործում
Այս հոդվածը կարդալուց հետո դուք որոշել եք, թե ձեր ծրագրի որ մասերը կարող են օգուտ քաղել հսկայական էջերից, որոնք՝ ոչ: Այսպիսով, հսկայական էջերը պետք է ընդհանրապես միացվեն:
Բարեբախտաբար դուք կարող եք օգտագործել madvise()միացնել հսկայական էջերը միայն այն հիշողության տարածքների համար, որտեղ դա օգտակար կլինի:
Նախ, ստուգեք, որ հսկայական էջերը աշխատում են madvise() ռեժիմով, օգտագործելով հրահանգներ հոդվածի սկզբում։
Այնուհետև օգտագործեք madvise()միջուկին հստակ ասել, թե որտեղ օգտագործել հսկայական էջերը:
#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)
Նկատի ունեցեք, որ այս մեթոդը պարզապես խորհուրդ է միջուկին, թե ինչպես կառավարել հիշողությունը: Սա չի նշանակում, որ միջուկը ավտոմատ կերպով կօգտագործի հսկայական էջեր տվյալ հիշողության համար:
Դիտեք փաստաթղթերը (manpage)madviseավելին իմանալ հիշողության կառավարման և madvise(), այս թեման ունի աներևակայելի կտրուկ ուսուցման կոր: Այսպիսով, եթե դուք մտադիր եք իսկապես լավ լինել դրանում, պատրաստվեք կարդալ և փորձարկել մի քանի շաբաթ՝ նախքան որևէ դրական արդյունք ակնկալելը: