Pythonin suorituskyky: natiivit NumPy-silmukat, takaisinkutsut ja konversiokustannukset
Hallittu, vain suorittimeen perustuva numeerinen testi seuraa identtisiä arvoja CPython-silmukoiden, NumPy-aritmetiikan, Python-takaisinkutsukääreen ja käännetyn Numba-silmukan kautta.
Hallittu, vain suorittimeen perustuva numeerinen testi seuraa identtisiä arvoja CPython-silmukoiden, NumPy-aritmetiikan, Python-takaisinkutsukääreen ja käännetyn Numba-silmukan kautta. Valmiilla syötteellä NumPylla oli suuri etumatka, kun taas muuntaminen Python-listoista ja takaisin Python-listoiksi vähensi tämän edun lähes tasapeliin. Jakso selittää suorituksen rajan ja miten mitata sovelluksen tarvitsemaa tulosta.
Lue kirjoitettu versio (englanniksi) ↗
Mitä tämä video käsittelee
- CPython kääntää lähdekoodin tavukoodiksi. Toistuva tulkki-/objektityö ja tyypitetty natiivi numeerinen silmukka ovat erilaisia suoritusjärjestelyjä.
- Numeerinen NumPy-aritmetiikka voi antaa tyypitettyjä eriä käännetylle toiminnolle; aritmeettinen silmukka on edelleen olemassa, ja näkymillä voi olla ei-yhtenäisiä asetteluja.
- Mittaa muuntaminen ja vaadittu tulosrepresentaatio. Tässä ajossa Python-listojen muuntaminen taulukoiksi ja takaisin pyyhkäisi pois suuren valmiin taulukon edun.
- Pienet työmäärät voivat suosia tavallista Pythonia, koska kiinteät taulukkokutsukustannukset ovat merkityksellisiä. Kahdeksan arvon ymmärrys voitti tämän mitatun vertailun.
- np.vectorize on apukääre, joka kutsuu Pythonia peräkkäisille elementeille; pelkkä eräkäyttöliittymä ei luo natiivia numeerista suoritusta.
- Käännetyt Python-syntaksisilukat voivat myös olla nopeita. Sisällytä kylmä käännös-/asetuskustannukset, kun ne ovat merkityksellisiä kutsujalle.
- Natiivi suoritus, CPU SIMD, monisäikeisyys ja GPU-taustajärjestelmät ovat erillisiä ajatuksia. Käytettävissä olevat CPU-ominaisuudet eivät jäljitä tietyssä ajossa käytettyjä ohjeita.
Käännetty transkriptio
Käännetty alkuperäisestä englanninkielisestä selostuksesta. Käytettävissä olevan äänen ja tekstitysten hallinta tapahtuu YouTuben kautta.
Miksi sama suoritin voi valmistua nopeammin?
0:00 Luulisi, että Python tarvitsee uuden kielen tullakseen nopeaksi. Sama suoritin suoritti erämme nopeammin silmukan siirryttyä. Minne työ katosi? Milloin nopeus häviää? Mikä oikopolku tuo Pythonin takaisin? Tämä on The Daily Diff, konepellin alla. Pidä silmällä sitä oikopolkua. CPython on standardi Python-toteutus.
0:17 Se kääntää lähdekoodisi tavukoodiksi ja suorittaa sitten nämä ohjeet tulkin avulla. NumPy on numeerinen kirjasto, jonka taulukot sisältävät arvoja, joilla on ilmoitettu tietotyyppi. Sen sisäänrakennettu aritmetiikka voi antaa koko erän käännetyille toiminnoille. Otetaan miljoona liukulukua, neliöidään jokainen, ja lisätään sitten alkuperäinen arvo. Jokainen versio saa identtiset arvot ja tuottaa vastaavat vastaukset. Arvot ovat riittävän pieniä pitämään pyöristyserot poissa kilpailusta.
0:40 Tällä koneella ymmärtäminen kesti noin kolmekymmentäkolme millisekuntia. NumPy kesti alle yhden. Molemmat toimivat suorittimella. Tämä on hyödyllinen todiste tälle työkuormitukselle, ja kauhea muistokirjoitus ohjelmointikielelle. Aloitetaan tavallisella silmukalla.
Mitä työtä Python-silmukka toistaa?
0:53 Python saa seuraavan arvon, suorittaa aritmetiikan ja liittää vastauksen. Sitten se tekee sen uudelleen. Kertolasku on edullinen. Seuraavan kertolaskun järjestäminen ja siihen liittyvien Python-olioiden käsittely lisää työtä joka kerta. Tämä on testatun funktion varsinainen purkaminen. Iterointi, kertolasku ja yhteenlasku ilmestyvät tavukoodiohjeina. Python-versiot ja tulkit tekevät erilaisia valintoja.
1:14 Nämä ajoitukset kuuluvat näytöllä olevaan versioon, joka on Python 3.10. Python-lista tallentaa viittauksia olioihin, joten erilaiset asiat voivat jakaa listan. Aritmeettinen tehtävämme käyttää numeroita kauttaaltaan. Se maksaa yleisestä järjestelystä pyytäessään toistuvaa palvelua. Kuvittele tilaavasi saman kahvin miljoona kertaa ja täyttäväsi uuden lomakkeen jokaiselle kupille. Kahvinkeitin on kunnossa.
1:36 Paperityö on kehittänyt oman uransa.
Mihin NumPy siirtää silmukan?
1:38 NumPy muuttaa sopimusta. Tämä taulukko sisältää kiinteän kokoisia liukulukuja yhdellä ilmoitetulla tyypillä. Taulukkomme on yhtenäinen, joten sen arvot sijaitsevat yhdessä muistissa. Näkymillä voi olla muita asetteluja. Aritmeettinen operaatio tietää, millaista dataa se saa. Kutsu antaa erän natiiville operaatiolle. Silmukka vierailee edelleen arvoissa käännetyn koodin sisällä. Se voi hyödyntää tyypin tuntemusta tässä työssä.
2:00 Python pysyy henkilönä, joka antaa tehtävän. Itamar Turner Trauring selittää eron Python Speedissä. Eräkäyttöliittymät, natiivit toteutukset ja prosessorin vektoriohjeet ovat erillisiä asioita. Funktion nimi antaa hyvin vähän todisteita.
Tarkoittaako nopea GPU:ta vai monta CPU-ydintä?
2:13 Tämä tulos käytti NumPya suorittimella. GPU-taustajärjestelmä, kuten CuPy, valitsee eri sijainnin taulukoille ja operaatioille. GPU:n ostaminen jättää tämän tavallisen Python-silmukan käymään siellä, missä se jo kävi. CPU:n vektoriohjeet voivat käsitellä useita arvoja samanaikaisesti. NumPylla on mekanismit tuettujen ytimien valitsemiseen. Ajonaikainen järjestelmämme ilmoittaa käytettävissä olevista ominaisuuksista, mutta ei jäljitä tämän lausekkeen ohjeita. Koko mitatun hyödyn antaminen vektoriohjeille liioittelisi todisteita.
2:40 GPU-ostoskori voi pysyä suljettuna. Suorituskyvyn parannuksessa on jotain syvästi tyydyttävää, joka myös peruuttaa oston. Valitettavasti vertailu jatkuu.
Milloin vaikuttava nopeus katoaa?
2:49 Kahdeksalla arvolla ymmärtäminen voitti. Taulukkokoneiston kutsuminen maksoi enemmän kuin pieni tehtävä. Suuremmat valmiit taulukot pääsivät edelle. Käytimme toistuvia kokeita ja lämmitettyä prosessia. Uudemmat Python-versiot voivat muuttaa risteystä. Sitten muutetaan sitä, mitä sovellus tarvitsee. Aloita Python-listalla ja lopeta uudella Python-listalla. NumPyn on muunnettava syöte taulukoksi ja muutettava vastaus takaisin Python-
3:11 olioiksi. Nämä vaiheet kuuluvat laskuun, jos sovelluksesi tarvitsee niitä. Miljoonalla arvolla tämä koko polku kesti noin kahdeksantoista millisekuntia. Ymmärtäminen kesti myös noin kahdeksantoista. Dramaattinen etumme muuttui lähes tasapeliksi. Nopea osa oli todellinen. Etu riippui siitä, että data sai pysyä numeerisessa muodossaan.
Mitkä rajat kuuluvat vertailuun?
3:28 Seuraa dataa. Jos seuraava operaatio hyväksyy taulukon, pidä taulukko. Jos muunnat toistuvasti listojen ja taulukoiden välillä, mittaa nuo ylitykset. Pysähtyminen ennen kallista luovutusta antaa tarkat luvut väärään kysymykseen. Tämän taulukon kertominen luo väliaikaisen tuloksen. Alkuperäisten arvojen lisääminen luo tulosteen. Natiivi suoritus tarvitsee edelleen muistia ja siirtää dataa.
3:47 Jotkut operaatiot hyväksyvät tulostuspuskurin, mikä vähentää varausten määrää, kun koodisi voi turvallisesti käyttää sitä uudelleen. Yksi kaunis rivi voi tilata useita suuria puskureita. Python Speed kutsuu tätä ongelmaa myös esiin. Varaaja on hämmästyttävän välinpitämätön estetiikastasi.
Voiko käännetty Python-silmukka olla myös nopea?
4:00 Voit myös säilyttää silmukan syntaksin ja muuttaa sen suoritusta. Numba voi kääntää tuetut numeeriset Python-funktiot natiivikoodiksi. Tässä on testistämme peräisin oleva silmukka kääntäjän dekoraattorillaan. Siinä lukee edelleen for. Kallis tulkin polku on muuttunut. Kääntämisen jälkeen tämä silmukka kesti alle puoli millisekuntia valmiilla taulukoilla. Itse kääntäminen kesti tässä ajossa noin sekunnin. Tämä asennuskustannus oli suljettu pois toistetuista ajoituksista,
4:22 joten pieni kertaluonteinen työ ansaitsee erilaisen vertailun. Numban oma opas näyttää mielellään eksplisiittisiä silmukoita. Kielen siirtymisen aloittaminen ennen kuuman polun löytämistä on monimutkainen tapa välttää profilointiohjelman avaamista. Ensin selvitetään, mikä kuluttaa aikaa. Verkon odotukset, objektien jäsentäminen ja massalaskenta vaativat erilaisia korjauksia. Natiivit taulukko-operaatiot auttavat, kun laskenta ja data sopivat.
4:43 Mittaa tulos, jota kutsujasi todella tarvitsee. Nyt siihen oikopolkuun. Sinulla on Python-funktio ja haluat, että se hyväksyy taulukon. vectorize-niminen kääre kuulostaa puuttuvalta suorituskykypainikkeelta. Sen dokumentaatiossa on tärkeä lause odottamassa.
Mitä np.vectorize todella suorittaa?
4:56 NumPy sanoo, että sen vectorize-kääre on tarkoitettu ensisijaisesti käyttömukavuuden vuoksi. Sen toteutus on pohjimmiltaan for-silmukka. Kääre hyväksyy erät, mutta jatkaa Python-funktion kutsumista peräkkäisille elementeille. Rajapinta lyheni. Suoritusraja pysyi kiireisenä. Katso, kuinka samat arvot tulevat takaisin Python-takaisinkutsun kautta. Valmiilla taulukoilla tämä versio kesti noin kahdeksankymmentäseitsemän millisekuntia. Se oli hitaampi kuin meidän ymmärryksemme.
5:18 Hyödyllinen broadcast-kääre voi säilyttää juuri sen elementtikohtaisen työn, jonka olit yrittänyt poistaa. Tarkista erärajapinnan takana oleva toteutus, pidä yhteensopiva data käyttökelpoisessa muodossaan ja sisällytä muuntaminen vertailuun. Natiivit, takaisinkutsut ja käännetyt silmukat voivat näyttää samanlaisilta kutsujan tuolilta. vectorize-nimi antoi lupauksen, jota sekuntikellosi ei koskaan allekirjoittanut. Säilytä se, kun tarvitset käyttömukavuutta. Suorituskyvyn vuoksi tarkista silmukka, joka suoritetaan.
Mitä sinun tulisi muuttaa koodissasi?
5:41 Tuomioni on SHIP IT mitatun numeerisen hot path -eräajoon. Pidä tavalliset silmukat, kun ne toimivat jo hyvin. Tarkista, missä työ tapahtuu ja mitä seuraava kutsuja tarvitsee. Tilaa, paina kelloa ja kerro kommenteissa, olisitko leimannut sen eri tavalla. Ja tämä on päivän The Daily Diff. Olen Niko Axrisista. Yhdistä vastuullisesti.
Lähteet
- 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



