# Python-ի արդյունավետություն. NumPy-ի բնիկ ցիկլեր, հետադարձ կանչեր և փոխակերպման ծախսեր

Published: 2026-10-17

CPU-ի վրա հիմնված թվային թեստը հետևում է նույնական արժեքներին CPython-ի ցիկլերի, NumPy-ի թվաբանության, Python-ի հետադարձ կանչի փաթաթիչի և կոմպիլացված Numba ցիկլի միջոցով: Պատրաստի-մուտքային NumPy-ն ուներ մեծ առավելություն, մինչդեռ Python-ի ցուցակներից և ցուցակներին փոխակերպումը նվազեցրեց այդ առավելությունը մինչև գրեթե ոչինչ: Դրվագը բացատրում է կատարման սահմանը և ինչպես չափել այն արդյունքը, որն անհրաժեշտ է հավելվածին:

Canonical: https://thedailydiff.dev/hy/video/2026-10-17-python-native-loops/

## Ինչ է ընդգրկում այս տեսանյութը

- CPython-ը կոդը կոմպիլացնում է բայթկոդի: Կրկնվող ինտերպրետատորի/օբյեկտի աշխատանքը և տիպավորված բնիկ թվային ցիկլը կատարման տարբեր կարգավորումներ են:
- Թվային NumPy-ի թվաբանությունը կարող է տիպավորված խմբաքանակները հանձնել կոմպիլացված գործողություններին; թվաբանական ցիկլը դեռ գոյություն ունի, և տեսքերը կարող են ունենալ ոչ հարակից դասավորություններ:
- Չափեք փոխակերպումը և պահանջվող ելքային ներկայացումը: Այս գործարկման ժամանակ Python-ի ցուցակները զանգվածների վերածելը և հետ վերադարձնելը ջնջել է պատրաստի զանգվածի մեծ առավելությունը:
- Փոքր ծանրաբեռնվածությունները կարող են նպաստել սովորական Python-ին, քանի որ ֆիքսված զանգվածի-կանչի ծախսերը կարևոր են: Ութ արժեքանոց ընկալումը շահել է այս չափված համեմատությունը:
- np.vectorize-ը հարմարավետության փաթաթիչ է, որը կանչում է Python-ը հաջորդական տարրերի համար; միայն խմբաքանակի ինտերֆեյսը չի հաստատում բնիկ թվային կատարում:
- Կոմպիլացված Python-ի շարահյուսության ցիկլերը նույնպես կարող են արագ լինել: Ներառեք սառը կոմպիլյացիայի/կարգավորման ծախսերը, երբ դրանք կարևոր են կանչողի համար:
- Բնիկ կատարումը, CPU SIMD-ը, բազմաթելայնությունը և GPU backends-ը առանձին գաղափարներ են: Առկա CPU-ի հնարավորությունները չեն հետևում կոնկրետ գործարկման մեջ օգտագործված հրահանգներին:

## Գլուխներ

- 0:00 Ինչու՞ նույն CPU-ն կարող է ավելի շուտ ավարտել:
- 0:52 Ի՞նչ աշխատանք է կրկնում Python-ի ցիկլը:
- 1:38 Ու՞ր է տեղափոխում NumPy-ն ցիկլը:
- 2:13 Արդյո՞ք արագ նշանակում է GPU կամ շատ CPU միջուկներ:
- 2:49 Ե՞րբ է անհետանում տպավորիչ արագացումը:
- 3:28 Ո՞ր սահմաններն են պատկանում բենչմարկին:
- 4:00 Կարո՞ղ է արդյոք կոմպիլացված Python-ի ցիկլը նույնպես արագ լինել:
- 4:56 Ի՞նչ է իրականում կատարում np.vectorize-ը:
- 5:41 Ի՞նչ պետք է փոխեք ձեր կոդում:

## Թարգմանված արձանագրություն

Թարգմանվել է բնօրինակ անգլերեն պատմությունից։ Հասանելի աուդիո և ենթագրերը վերահսկվում են YouTube-ի կողմից։

### Ինչու՞ նույն CPU-ն կարող է ավելի շուտ ավարտել:

0:00 Դուք կարծում եք, որ Python-ին նոր լեզու է անհրաժեշտ՝ արագանալու համար: Նույն CPU-ն մեր խմբաքանակն ավելի արագ է գործարկել այն բանից հետո, երբ ցիկլը տեղափոխվել է: Ո՞ւր է գնացել աշխատանքը: Ե՞րբ է արագացումը անհետանում: Ո՞ր դյուրանցումն է Python-ին վերադարձնում: Սա The Daily Diff-ն է, ներքին տեսանկյունից: Աչքիդ առաջ պահիր այդ դյուրանցումը: CPython-ը Python-ի ստանդարտ իրականացումն է:

0:17 Այն կոմպիլացնում է ձեր աղբյուրը բայթկոդի, այնուհետև գործարկում է այդ հրահանգները ինտերպրետատորում: NumPy-ն թվային գրադարան է, որի զանգվածները պահում են արժեքներ հայտարարված տվյալների տեսակով: Դրա ներկառուցված թվաբանությունը կարող է ամբողջ խմբաքանակը հանձնել կոմպիլացված գործողություններին: Վերցրեք մեկ միլիոն լողացող կետի արժեք, յուրաքանչյուրը քառակուսի բարձրացրեք, այնուհետև ավելացրեք սկզբնական արժեքը: Յուրաքանչյուր տարբերակ ստանում է նույնական արժեքներ և տալիս համընկնող պատասխաններ: Արժեքները բավականաչափ փոքր են՝ կլորացման տարբերությունները մրցավազքից դուրս պահելու համար:

0:40 Այս մեքենայի վրա ընկալումը տևել է մոտ երեսուն երեք միլիվայրկյան: NumPy-ն տևել է մեկից պակաս: Երկուսն էլ աշխատել են CPU-ի վրա: Դա օգտակար ապացույց է այս ծանրաբեռնվածության համար, և սարսափելի մահախոսական ծրագրավորման լեզվի համար: Սկսենք սովորական ցիկլից:

### Ի՞նչ աշխատանք է կրկնում Python-ի ցիկլը:

0:53 Python-ը ստանում է հաջորդ արժեքը, կատարում է թվաբանական գործողությունը և ավելացնում է պատասխանը: Այնուհետև այն նորից անում է դա: Բազմապատկումը էժան է: Հաջորդ բազմապատկումը կազմակերպելը և դրա շուրջ Python-ի օբյեկտները մշակելը, ամեն անգամ ավելացնում է աշխատանք: Սա փորձարկված ֆունկցիայի իրական դիսասեմբլինգն է: Իտերացիան, բազմապատկումը և գումարումը հայտնվում են որպես բայթկոդի հրահանգներ: Python-ի տարբերակները և ինտերպրետատորները տարբեր ընտրություններ են կատարում:

1:14 Այս ժամանակները պատկանում են էկրանին երևացող տարբերակին, որը Python երեք կետ տասն է: Python-ի ցուցակը պահում է օբյեկտների հղումներ, այնպես որ տարբեր տեսակի բաներ կարող են կիսել մեկ ցուցակ: Մեր թվաբանական աշխատանքը ամբողջությամբ օգտագործում է թվեր: Այն վճարում է ընդհանուր կարգավորման համար՝ կրկնվող ծառայություն խնդրելով: Պատկերացրեք, որ մեկ միլիոն անգամ պատվիրում եք նույն սուրճը և լրացնում եք նոր ձևաթուղթ յուրաքանչյուր բաժակի համար: Սուրճի մեքենան լավ է:

1:36 Թղթաբանությունը զարգացրել է իր սեփական կարիերան:

### Ու՞ր է տեղափոխում NumPy-ն ցիկլը:

1:38 NumPy-ն փոխում է պայմանագիրը: Այս զանգվածը պարունակում է ֆիքսված չափի լողացող կետի արժեքներ մեկ հայտարարված տեսակով: Մեր զանգվածը հարակից է, ուստի դրա արժեքները հիշողության մեջ միասին են գտնվում: Տեսքերը կարող են ունենալ այլ դասավորություններ: Թվաբանական գործողությունը գիտի, թե ինչ տեսակի տվյալներ է ստանում: Կանչը խմբաքանակը հանձնում է բնիկ գործողությանը: Ցիկլը դեռ այցելում է արժեքներին կոմպիլացված կոդի ներսում: Այն կարող է վերօգտագործել տեսակի մասին գիտելիքները այդ աշխատանքի ընթացքում:

2:00 Python-ը մնում է այն մարդը, ով հանձնում է աշխատանքը: Իտամար Թըրներ Թրաուրինգը բացատրում է տարբերությունը Python Speed-ում: Խմբաքանակի ինտերֆեյսները, բնիկ իրականացումները և պրոցեսորի վեկտորային հրահանգները առանձին բաներ են: Ֆունկցիայի անունը շատ քիչ ապացույց է տրամադրում:

### Արդյո՞ք արագ նշանակում է GPU կամ շատ CPU միջուկներ:

2:13 Այս արդյունքը օգտագործել է NumPy-ն CPU-ի վրա: GPU backend-ը, ինչպես CuPy-ն, ընտրում է այլ տուն զանգվածների և գործողությունների համար: GPU գնելը այս սովորական Python-ի ցիկլը թողնում է այնտեղ, որտեղ այն արդեն աշխատում էր: CPU-ի վեկտորային հրահանգները կարող են միաժամանակ մշակել մի քանի արժեք: NumPy-ն ունի մեխանիզմներ աջակցվող միջուկները ընտրելու համար: Մեր runtime-ը հայտնում է առկա հնարավորությունները, բայց չի հետևում այս արտահայտության հրահանգներին: Ամբողջ չափված շահը վեկտորային հրահանգներին տալը կգերագնահատեր ապացույցները:

2:40 GPU-ի գնումների զամբյուղը կարող է փակ մնալ: Կատարողականի շտկման մեջ խորը բավարարություն կա, որը նաև չեղարկում է գնումը: Ցավոք, բենչմարկը շարունակվում է:

### Ե՞րբ է անհետանում տպավորիչ արագացումը:

2:49 Ութ արժեքով, ընկալումը հաղթեց: Զանգվածի մեխանիզմը կանչելը ավելի շատ արժեր, քան փոքրիկ աշխատանքը: Ավելի մեծ պատրաստի զանգվածները առաջ անցան: Մենք օգտագործեցինք կրկնվող փորձարկումներ և տաքացված գործընթաց: Ավելի նոր Python-ի կառուցվածքները կարող են փոխել անցումը: Այնուհետև փոխեք այն, ինչ անհրաժեշտ է հավելվածին: Սկսեք Python-ի ցուցակից և ավարտեք նոր Python-ի ցուցակով: NumPy-ն պետք է մուտքը վերածի զանգվածի և պատասխանը նորից վերածի Python-ի

3:11 օբյեկտների: Այդ քայլերը պատկանում են հաշվին, եթե ձեր հավելվածին դրանք անհրաժեշտ են: Մեկ միլիոն արժեքի դեպքում, այդ ամբողջական ուղին տևել է մոտ քսանութ միլիվայրկյան: Ընկալումը նույնպես տևել է մոտ քսանութ: Մեր դրամատիկ առավելությունը դարձավ գրեթե ոչինչ: Արագ մասը իրական էր: Առավելությունը կախված էր նրանից, թե արդյոք տվյալները մնում էին իրենց թվային տեսքով:

### Ո՞ր սահմաններն են պատկանում բենչմարկին:

3:28 Հետևեք տվյալներին: Եթե հաջորդ գործողությունը ընդունում է զանգված, պահպանեք զանգվածը: Եթե դուք բազմիցս փոխակերպում եք ցուցակների և զանգվածների միջև, չափեք այդ անցումները: Թանկարժեք հանձնումից առաջ կանգ առնելը ճշգրիտ թվեր է տալիս սխալ հարցի համար: Այս զանգվածը բազմապատկելը ստեղծում է ժամանակավոր արդյունք: Սկզբնական արժեքները գումարելը ստեղծում է ելքը: Բնիկ կատարումը դեռ կարիք ունի հիշողության և տվյալներ է տեղափոխում:

3:47 Որոշ գործողություններ ընդունում են ելքային բուֆեր՝ նվազեցնելով հատկացումները, երբ ձեր կոդը կարող է անվտանգ վերօգտագործել այն: Մեկ գեղեցիկ գիծը կարող է մի քանի մեծ բուֆեր պատվիրել: Python Speed-ը նույնպես նշում է այս խնդիրը: Հատկացնողը զարմանալիորեն անտարբեր է ձեր գեղագիտության նկատմամբ:

### Կարո՞ղ է արդյոք կոմպիլացված Python-ի ցիկլը նույնպես արագ լինել:

4:00 Կարող եք նաև պահպանել ցիկլի շարահյուսությունը և փոխել դրա կատարումը: Numba-ն կարող է աջակցվող թվային Python ֆունկցիաները կոմպիլացնել բնիկ կոդի: Ահա մեր թեստի ցիկլը իր կոմպիլյատորի դեկորատորով: Այն դեռ ասում է for: Թանկարժեք ինտերպրետատորի ուղին փոխվել է: Կոմպիլյացիայից հետո այս ցիկլը տևել է կես միլիվայրկյանից պակաս՝ պատրաստի զանգվածներով: Կոմպիլյացիան ինքնին տևել է մոտ մեկ վայրկյան այս գործարկման ժամանակ: Այդ կարգավորման ծախսը բացառվել է կրկնվող ժամանակներից,

4:22 այսպիսով, փոքրիկ մեկանգամյա աշխատանքը արժանի է այլ համեմատության: Numba-ի սեփական ուղեցույցը ուրախ է ցուցադրել հստակ ցիկլեր: Լեզվի միգրացիա սկսելը մինչև թեժ ուղին գտնելը բարդ միջոց է խուսափելու profiler բացելուց: Նախ գտեք, թե ինչն է սպառում ժամանակը: Ցանցային սպասումները, օբյեկտների վերլուծությունը և զանգվածային թվաբանությունը տարբեր շտկումներ են պահանջում: Բնիկ զանգվածային գործողություններն օգնում են, երբ հաշվարկը և տվյալները համապատասխանում են:

4:43 Չափեք այն արդյունքը, որն իրականում անհրաժեշտ է ձեր կանչողին: Հիմա այդ դյուրանցման մասին: Դուք ունեք Python ֆունկցիա և ցանկանում եք, որ այն ընդունի զանգված: vectorize անունով փաթաթիչը հնչում է որպես կատարողականի բացակայող կոճակ: Դրա փաստաթղթավորումն ունի սպասող կարևոր նախադասություն:

### Ի՞նչ է իրականում կատարում np.vectorize-ը:

4:56 NumPy-ն ասում է, որ իր vectorize փաթաթիչը տրամադրվում է հիմնականում հարմարավետության համար: Դրա իրականացումը հիմնականում for ցիկլ է: Փաթաթիչը ընդունում է խմբաքանակներ, բայց շարունակում է կանչել ձեր Python ֆունկցիան հաջորդական տարրերի համար: Ինտերֆեյսը կարճացավ: Կատարման սահմանը մնաց զբաղված: Դիտեք նույն արժեքները, որոնք վերադառնում են Python-ի հետադարձ կանչի միջոցով: Պատրաստի զանգվածներով այս տարբերակը տևել է մոտ ութսունյոթ միլիվայրկյան: Այն ավելի դանդաղ էր, քան մեր ընկալումը:

5:18 Օգտակար broadcasting փաթաթիչը կարող է պահպանել յուրաքանչյուր տարրի ճշգրիտ աշխատանքը, որը դուք փորձում էիք հեռացնել: Ստուգեք խմբաքանակի ինտերֆեյսի հետևում գտնվող իրականացումը, համատեղելի տվյալները պահպանեք իրենց օգտակար տեսքով, և համեմատության մեջ ներառեք փոխակերպումը: Բնիկ, հետադարձ կանչի և կոմպիլացված ցիկլերը կարող են նման տեսք ունենալ կանչողի աթոռից: vectorize անունը խոստում էր տալիս, որը ձեր վայրկենաչափը երբեք չի ստորագրել: Պահեք այն, երբ հարմարավետությունն է ձեզ անհրաժեշտ: Կատարողականի համար ստուգեք աշխատող ցիկլը:

### Ի՞նչ պետք է փոխեք ձեր կոդում:

5:41 Իմ դատավճիռն է SHIP IT՝ չափված թվային թեժ ուղու խմբաքանակի համար: Պահեք սովորական ցիկլերը, երբ դրանք արդեն լավ են աշխատում: Ստուգեք, թե որտեղ է կատարվում աշխատանքը և ինչ է անհրաժեշտ հաջորդ կանչողին: Բաժանորդագրվեք, սեղմեք զանգակը և մեկնաբանություններում ինձ ասեք, եթե այն այլ կերպ կդրոշմեիք: Եվ սա այսօրվա տարբերությունն է: Ես Նիկոն եմ Axrisi-ից: Միավորել պատասխանատվությամբ:

## Աղբյուրներ

- [Universal functions (ufunc) basics — NumPy 2.2](https://numpy.org/doc/2.2/user/basics.ufuncs.html) — NumPy
- [The N-dimensional array — NumPy 2.2](https://numpy.org/doc/2.2/reference/arrays.ndarray.html) — NumPy
- [numpy.vectorize — convenience and performance notes](https://numpy.org/doc/2.2/reference/generated/numpy.vectorize.html) — NumPy
- [CPU/SIMD optimizations — NumPy 2.2](https://numpy.org/doc/2.2/reference/simd/index.html) — NumPy
- [dis — Disassembler for Python bytecode](https://docs.python.org/3.10/library/dis.html) — Python Software Foundation
- [CPython 3.10.12 list representation](https://github.com/python/cpython/blob/v3.10.12/Include/cpython/listobject.h) — CPython contributors
- [The limits of Python vectorization as a performance technique](https://pythonspeed.com/articles/vectorization-python-alternatives/) — Itamar Turner-Trauring / Python⇒Speed
- [Performance Tips](https://numba.readthedocs.io/en/stable/user/performance-tips.html) — Numba
- [Basics of CuPy](https://docs.cupy.dev/en/stable/user_guide/basic.html) — CuPy
