Performanca e Python: cikle vendase NumPy, rikthime dhe kostot e konvertimit
Një test numerik i kontrolluar vetëm për CPU ndjek vlera identike përmes cikleve CPython, aritmetikës NumPy, një mbështjellësi rikthimi Python dhe një cikli të përpiluar Numba.
Një test numerik i kontrolluar vetëm për CPU ndjek vlera identike përmes cikleve CPython, aritmetikës NumPy, një mbështjellësi rikthimi Python dhe një cikli të përpiluar Numba. NumPy me hyrje të gatshme kishte një avantazh të madh, ndërsa konvertimi nga dhe në listat Python e reduktoi atë avantazh në një barazim pothuajse. Episodi shpjegon kufirin e ekzekutimit dhe si të matet rezultati që i duhet një aplikacioni.
Lexoni edicionin e shkruar (anglisht) ↗
Çfarë mbulon kjo video
- CPython përpilon burimin në bytecode. Puna e përsëritur e interpretuesit/objektit dhe një cikël numerik vendas i tipizuar janë rregullime të ndryshme ekzekutimi.
- Aritmetika numerike NumPy mund t'i japë grupe të tipizuara operacioneve të kompiluara; cikli aritmetik ende ekziston, dhe pamjet mund të kenë vendosje jo të vazhdueshme.
- Matni konvertimin dhe paraqitjen e kërkuar të daljes. Në këtë ekzekutim, konvertimi i listave Python në grupe dhe kthim mbrapsht fshiu epërsinë e madhe të grupit të gatshëm.
- Ngarkesat e vogla të punës mund të favorizojnë Python-in e zakonshëm sepse kostot fikse të thirrjes së grupit kanë rëndësi. Kuptueshmëria me tetë vlera fitoi këtë krahasim të matur.
- np.vectorize është një mbështjellës lehtësimi që thërret Python për elemente të njëpasnjëshme; një ndërfaqe grupi nuk vendos vetëm ekzekutim numerik vendas.
- Ciklet e përpiluara me sintaksë Python mund të jenë gjithashtu të shpejta. Përfshini kostot e përpilimit/konfigurimit të ftohtë kur ato kanë rëndësi për thirrësin.
- Ekzekutimi vendas, CPU SIMD, multithreading dhe backend-et GPU janë ide të ndara. Karakteristikat e disponueshme të CPU-së nuk gjurmojnë udhëzimet e përdorura në një ekzekutim të veçantë.
Transkript i përkthyer
Përkthyer nga tregimi origjinal në anglisht. Audio dhe titrat e disponueshme kontrollohen nga YouTube.
Pse i njëjti CPU mund të përfundojë më shpejt?
0:00 Ju mendoni se Python ka nevojë për një gjuhë të re për t'u bërë i shpejtë. I njëjti CPU ekzekutoi grupin tonë më shpejt pasi u zhvendos cikli. Ku shkoi puna? Kur zhduket shpejtësia? Cila shkurtore e kthen Python-in? Ky është The Daily Diff, nën kapak. Mbani një sy në atë shkurtore. CPython është implementimi standard i Python.
0:17 Ai përpilon burimin tuaj në bytecode, pastaj ekzekuton ato udhëzime në një interpretues. NumPy është një bibliotekë numerike, ku rreshtat mbajnë vlera me një lloj të deklaruar të të dhënave. Aritmetika e tij e integruar mund t'i kalojë një grupi të tërë operacioneve të përpiluara. Merrni një milion vlera me pikë lundruese, katrorizoni secilën prej tyre, pastaj shtoni vlerën origjinale. Çdo version merr vlera identike dhe prodhon përgjigje të përputhshme. Vlerat janë aq të vogla sa të mos lejojnë diferencat e rrumbullakimit të hyjnë në garë.
0:40 Në këtë makinë, kuptimi zgjati rreth tridhjetë e tre milisekonda. NumPy mori më pak se një. Të dyja ekzekutuan në CPU. Kjo është një provë e dobishme për këtë ngarkesë pune, dhe një nekrologji e tmerrshme për një gjuhë programimi. Filloni me ciklin e zakonshëm.
Çfarë pune përsërit një cikël Python?
0:53 Python merr vlerën tjetër, kryen aritmetikën dhe shton përgjigjen. Pastaj e bën këtë përsëri. Shumëzimi është i lirë. Rregullimi i shumëzimit të ardhshëm, dhe trajtimi i objekteve Python rreth tij, shton punë çdo herë. Ky është çmontimi aktual i funksionit të testuar. Iterimi, shumëzimi dhe mbledhja shfaqen si udhëzime bytecode. Versionet dhe interpretuesit e Python bëjnë zgjedhje të ndryshme.
1:14 Këto kohë matjeje i përkasin versionit në ekran, i cili është Python tre pikë dhjetë. Një listë Python ruan referenca ndaj objekteve, kështu që lloje të ndryshme gjërash mund të ndajnë një listë. Detyra jonë aritmetike përdor numra në tërësi. Ajo paguan për një rregullim të përgjithshëm duke kërkuar një shërbim të përsëritur. Imagjinoni të porosisni të njëjtin kafe një milion herë dhe të plotësoni një formular të ri për çdo filxhan. Makina e kafesë është mirë.
1:36 Dokumentacioni ka zhvilluar karrierën e vet.
Ku e lëviz NumPy ciklin?
1:38 NumPy ndryshon kontratën. Ky rresht mban vlera me pikë lundruese me madhësi fikse me një lloj të deklaruar. Rreshti ynë është i vazhdueshëm, kështu që vlerat e tij qëndrojnë së bashku në memorie. Pamjet mund të kenë vendosje të tjera. Operacioni aritmetik e di se çfarë lloj të dhënash po merr. Thirrja ia kalon grupin një operacioni vendas. Një cikël ende viziton vlerat brenda kodit të përpiluar. Ai mund të ripërdorë njohuritë e tipit nëpër atë punë.
2:00 Python mbetet personi që ia dorëzon punën. Itamar Turner Trauring shpjegon dallimin në Python Speed. Ndërfaqet e grupeve, zbatimet vendase dhe udhëzimet e vektorit të procesorit janë gjëra të ndara. Emri i funksionit ofron shumë pak prova.
A do të thotë shpejtësi GPU apo shumë bërthama CPU?
2:13 Ky rezultat përdori NumPy në CPU. Një backend GPU si CuPy zgjedh një shtëpi tjetër për rreshtat dhe operacionet. Blerja e një GPU e lë këtë cikël të zakonshëm Python të funksionojë aty ku tashmë funksiononte. Udhëzimet e vektorit të CPU-së mund të përpunojnë disa vlera së bashku. NumPy ka makineri për zgjedhjen e bërthamave të mbështetura. Koha jonë e ekzekutimit raporton funksionet e disponueshme, por nuk gjurmon udhëzimet e kësaj shprehjeje. T'ia jepje të gjithë fitimin e matur udhëzimeve të vektorit do të ekzagjeronte provat.
2:40 Karroca e blerjeve të GPU mund të qëndrojë e mbyllur. Ka diçka thellësisht kënaqëse në lidhje me një rregullim të performancës që gjithashtu anulon një blerje. Fatkeqësisht, benchmark-u vazhdon.
Kur zhduket shpejtësia mbresëlënëse?
2:49 Me tetë vlera, kuptimi fitoi. Thirrja e makinerisë së rreshtave kushtoi më shumë se detyra e vogël. Rreshtat më të mëdhenj të gatshëm kaluan përpara. Ne përdorëm prova të përsëritura dhe një proces të ngrohur. Ndërtimet më të reja të Python mund të ndryshojnë kalimin. Pastaj ndryshoni atë që i duhet aplikacionit. Filloni me një listë Python dhe mbaroni me një listë të re Python. NumPy duhet të konvertojë hyrjen në një rresht dhe të kthejë përgjigjen në objekte Python.
3:11 Këto hapa i përkasin faturës nëse aplikacioni juaj i kërkon ato. Në një milion vlera, kjo rrugë e plotë zgjati rreth njëzet e tetë milisekonda. Kuptimi zgjati gjithashtu rreth njëzet e tetë. Avantazhi ynë dramatik u bë pothuajse barazim. Pjesa e shpejtë ishte reale. Avantazhi varej nga lejimi i të dhënave të qëndronin në formën e tyre numerike.
Cilat kufij i përkasin benchmark-ut?
3:28 Ndjek të dhënat. Nëse operacioni tjetër pranon një rresht, mbani rreshtin. Nëse vazhdimisht konvertoni ndërmjet listave dhe rreshtave, matni ato kalime. Ndalimi para një dorëzimi të shtrenjtë jep numra të saktë për pyetjen e gabuar. Shumëzimi i këtij rreshti krijon një rezultat të përkohshëm. Shtimi i vlerave origjinale krijon daljen. Ekzekutimi vendas ende ka nevojë për memorie dhe lëviz të dhëna.
3:47 Disa operacione pranojnë një bufer daljeje, duke reduktuar ndarjet kur kodi juaj mund ta ripërdorë atë në mënyrë të sigurt. Disa operacione pranojnë një bufer daljeje, duke reduktuar ndarjet kur kodi juaj mund të ripërdorë atë në mënyrë të sigurt. Një rresht i bukur mund të porosisë disa bufera të mëdha. Python Speed thekson edhe këtë problem. Alokuesi është jashtëzakonisht indiferent ndaj estetikës suaj.
A mund të jetë i shpejtë edhe një cikël Python i kompiluar?
4:00 Mund të ruani edhe sintaksën e ciklit dhe të ndryshoni ekzekutimin e tij. Numba mund të përpilojë funksionet numerike të mbështetura të Python në kod vendas. Këtu është cikli nga testi ynë me dekoratorin e kompiluesit. Ende thotë për. Shtegu i shtrenjtë i interpretuesit ka ndryshuar. Pas kompilimit, ky cikël zgjati më pak se gjysmë milisekondi me rreshta të gatshëm. Vetë kompilimi zgjati rreth një sekondë në këtë ekzekutim. Kjo kosto konfigurimi u përjashtua nga matjet e përsëritura,
4:22 kështu që një punë e vogël e vetme meriton një krahasim të ndryshëm. Udhëzuesi i vetë Numba-s është i lumtur të tregojë cikle të qarta. Fillimi i një migrimi të gjuhës para se të gjesh shtegun e nxehtë është një mënyrë e ndërlikuar për të shmangur hapjen e një profiluesi. Së pari gjeni se çfarë konsumon kohën. Pritjet e rrjetit, analizimi i objekteve dhe aritmetika e madhe kërkojnë zgjidhje të ndryshme. Operacionet e rreshtave vendas ndihmojnë kur llogaritja dhe të dhënat përshtaten.
4:43 Matni rezultatin që thirrësi juaj ka nevojë në të vërtetë. Tani për atë shkurtore. Ju keni një funksion Python dhe dëshironi që ai të pranojë një rresht. Një mbështjellës i quajtur vectorize tingëllon si butoni i performancës që mungon. Dokumentacioni i tij ka një fjali të rëndësishme në pritje.
Çfarë ekzekuton në të vërtetë np.vectorize?
4:56 NumPy thotë se mbështjellësi i tij vectorize ofrohet kryesisht për lehtësi. Implementimi i tij është thelbësisht një cikël for. Mbështjellësi pranon grupe, por vazhdon të thërrasë funksionin tuaj Python për elemente të njëpasnjëshme. Ndërfaqja u shkurtua. Kufiri i ekzekutimit mbeti i zënë. Shikoni të njëjtat vlera të kthehen përmes thirrjes Python. Me rreshta të gatshëm, ky version zgjati rreth tetëdhjetë e shtatë milisekonda. Ishte më i ngadaltë se kuptimi ynë.
5:18 Një mbështjellës i dobishëm transmetimi mund të ruajë punën e saktë për element, të cilën po përpiqeshit ta hiqnit. Kontrolloni implementimin pas një ndërfaqeje grupi, mbani të dhënat e pajtueshme në formën e tyre të dobishme dhe përfshini konvertimin në krahasim. Kontrolloni implementimin pas një ndërfaqeje grupi, mbani të dhënat e pajtueshme në formën e tyre të dobishme, dhe përfshini konvertimin në krahasim. Ciklet vendase, të rikthyera dhe të kompiluara mund të duken të ngjashme nga karrigia e thirrësit. Emri vectorize bëri një premtim që kronometri juaj nuk e nënshkroi kurrë. Mbajeni kur lehtësia është ajo që ju duhet. Për performancë, kontrolloni ciklin që ekzekutohet.
Çfarë duhet të ndryshoni në kodin tuaj?
5:41 Vendimi im është SHIP IT për grupimin e një shtegu numerik të nxehtë të matur. Mbani ciklet e zakonshme kur ato tashmë funksionojnë mirë. Kontrolloni se ku ndodh puna dhe çfarë i duhet thirrësit tjetër. Abonohuni, shtypni zilen dhe më tregoni në komente nëse do ta kishit vulosur ndryshe. Dhe ky është ndryshimi për sot. Unë jam Niko nga Axrisi. Bashkohuni me përgjegjësi.
Burimet
- Universal functions (ufunc) basics — NumPy 2.2NumPy
- The N-dimensional array — NumPy 2.2NumPy
- numpy.vectorize — convenience and performance notesNumPy
- CPU/SIMD optimizations — NumPy 2.2NumPy
- dis — Disassembler for Python bytecodePython Software Foundation
- CPython 3.10.12 list representationCPython contributors
- The limits of Python vectorization as a performance techniqueItamar Turner-Trauring / Python⇒Speed
- Performance TipsNumba
- Basics of CuPyCuPy



