+− THE DAILY DIFFdev & AI news
SHIP IT

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

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

Want to see our stories first on Google? Add us to your preferred sources — it helps us grow.

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

Կարդացեք գրավոր տարբերակը (անգլերեն) ↗

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

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

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

Թարգմանվել է բնօրինակ անգլերեն պատմությունից։ Հասանելի աուդիո և ենթագրերը վերահսկվում են 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-ից: Միավորել պատասխանատվությամբ:

Աղբյուրներ

  1. Universal functions (ufunc) basics — NumPy 2.2NumPy
  2. The N-dimensional array — NumPy 2.2NumPy
  3. numpy.vectorize — convenience and performance notesNumPy
  4. CPU/SIMD optimizations — NumPy 2.2NumPy
  5. dis — Disassembler for Python bytecodePython Software Foundation
  6. CPython 3.10.12 list representationCPython contributors
  7. The limits of Python vectorization as a performance techniqueItamar Turner-Trauring / Python⇒Speed
  8. Performance TipsNumba
  9. Basics of CuPyCuPy

Հարակից տեսանյութեր

under-the-hood · hy · 12 հոկ, 2026 թ.

Hugging Face մոդելային ֆայլերը կարող են թաքնված կոդ գործարկել

Չարամիտ մոդելային փաթեթները կարող են կոդ կատարել անապահով բեռնման ժամանակ։ Երեք փաստագրված օրինակ բացատրում են Pickle-ի հակադարձ շելլերը, կոտրված ֆայլերի սկաների վարքագիծը և հետազոտությամբ ցուցադրված

3:33 ↗
under-the-hood · hy · 11 հոկ, 2026 թ.

Stripe-ը հիշում է Ձեր հարցումը, երբ պատասխանն անհետանում է

Ժամանակի սահմանաչափը կարող է անորոշ թողնել վճարումը, երբ սերվերը ավարտել է գործողությունը։ «Under the Hood» բացատրությունը օգտագործում է Stripe API v1-ի փաստաթղթավորված իդեմպոտենտության պայմանագիրը՝ ց

2:54 ↗