# Rendiment de Python: bucles natius de NumPy, callbacks i costos de conversió

Published: 2026-10-17

Una prova numèrica controlada només amb CPU segueix valors idèntics a través de bucles CPython, aritmètica NumPy, un embolcall de callback de Python i un bucle Numba compilat. NumPy amb entrada ja preparada va tenir un gran avantatge, mentre que la conversió d'anada i tornada a llistes de Python va reduir aquest avantatge fins a un gairebé empat. L'episodi explica el límit d'execució i com mesurar el resultat que una aplicació necessita.

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

## Què cobreix aquest vídeo

- CPython compila el codi font a bytecode. El treball repetit d'intèrpret/objecte i un bucle numèric natiu tipat són arranjaments d'execució diferents.
- L'aritmètica numèrica de NumPy pot passar lots tipats a operacions compilades; el bucle aritmètic encara existeix, i les vistes poden tenir dissenys no contigus.
- Mesureu la conversió i la representació de sortida requerida. En aquesta execució, la conversió de llistes de Python a arrays i viceversa va esborrar el gran avantatge de l'array ja preparat.
- Les càrregues de treball petites poden afavorir el Python ordinari perquè els costos fixos de les trucades a arrays són importants. La comprensió de vuit valors va guanyar aquesta comparació mesurada.
- np.vectorize és un embolcall de conveniència que crida a Python per a elements successius; una interfície de lot per si sola no estableix l'execució numèrica nativa.
- Els bucles compilats amb sintaxi Python també poden ser ràpids. Incloeu els costos de compilació/configuració en fred quan siguin importants per a la persona que truca.
- L'execució nativa, el SIMD de la CPU, el multithreading i els backends de GPU són idees separades. Les característiques de la CPU disponibles no tracen les instruccions utilitzades en una execució particular.

## Capítols

- 0:00 Per què la mateixa CPU pot acabar abans?
- 0:52 Quin treball repeteix un bucle Python?
- 1:38 On mou NumPy el bucle?
- 2:13 Vol dir ràpid GPU o molts nuclis de CPU?
- 2:49 Quan desapareix l'impressionant augment de velocitat?
- 3:28 Quins límits pertanyen al benchmark?
- 4:00 Un bucle Python compilat també pot ser ràpid?
- 4:56 Què executa realment np.vectorize?
- 5:41 Què hauries de canviar en el teu codi?

## Transcripció traduïda

Traduït de la narració original en anglès. L'àudio i els subtítols disponibles estan controlats per YouTube.

### Per què la mateixa CPU pot acabar abans?

0:00 Creus que Python necessita un nou llenguatge per ser ràpid. La mateixa CPU va executar el nostre lot més ràpid després que el bucle es mogués. On va anar el treball? Quan s'esvaeix l'acceleració? Quin drecera torna Python? Això és The Daily Diff, sota el capó. Vigila aquesta drecera. CPython és la implementació estàndard de Python.

0:17 Compila el vostre codi font en bytecode, i després executa aquestes instruccions en un intèrpret. NumPy és una biblioteca numèrica els arrays de la qual contenen valors amb un tipus de dades declarat. La seva aritmètica integrada pot lliurar un lot sencer a operacions compilades. Preneu un milió de valors de punt flotant, eleveu cadascun al quadrat, després afegiu el valor original. Cada versió obté valors idèntics i produeix respostes que coincideixen. Els valors són prou petits per mantenir les diferències d'arrodoniment fora de la carrera.

0:40 En aquesta màquina, la comprensió va trigar uns trenta-tres mil·lisegons. NumPy va trigar menys d'un. Tots dos es van executar a la CPU. Això és una prova útil per a aquesta càrrega de treball, i un obituari terrible per a un llenguatge de programació. Comenceu amb el bucle ordinari.

### Quin treball repeteix un bucle Python?

0:53 Python obté el següent valor, realitza l'aritmètica i afegeix la resposta. Després ho fa de nou. La multiplicació és barata. Organitzar la següent multiplicació i gestionar els objectes de Python al seu voltant, afegeix treball cada vegada. Aquesta és la desassemblació real de la funció provada. La iteració, la multiplicació i l'addició apareixen com a instruccions de bytecode. Les versions i intèrprets de Python fan eleccions diferents.

1:14 Aquests temps pertanyen a la versió en pantalla, que és Python tres punt deu. Una llista de Python emmagatzema referències a objectes, de manera que diferents tipus de coses poden compartir una llista. La nostra tasca aritmètica utilitza números en tot moment. Paga per un arranjament general mentre sol·licita un servei repetitiu. Imagineu demanar el mateix cafè un milió de vegades i omplir un formulari nou per a cada tassa. La màquina de cafè està bé.

1:36 La paperassa ha desenvolupat la seva pròpia carrera.

### On mou NumPy el bucle?

1:38 NumPy canvia el contracte. Aquest array conté valors de punt flotant de mida fixa amb un tipus declarat. El nostre array és contigu, de manera que els seus valors es troben junts a la memòria. Les vistes poden tenir altres dissenys. L'operació aritmètica sap quin tipus de dades està rebent. La crida lliura el lot a una operació nativa. Un bucle encara visita els valors dins del codi compilat. Pot reutilitzar el coneixement del tipus en tot aquest treball.

2:00 Python segueix sent la persona que lliura la feina. Itamar Turner Trauring explica la distinció a Python Speed. Les interfícies de lot, les implementacions natives i les instruccions vectorials del processador són coses separades. El nom de la funció proporciona molt poca evidència.

### Vol dir ràpid GPU o molts nuclis de CPU?

2:13 Aquest resultat va utilitzar NumPy a la CPU. Un backend de GPU com CuPy tria una llar diferent per a arrays i operacions. Comprar una GPU deixa aquest bucle Python ordinari funcionant on ja funcionava. Les instruccions vectorials de la CPU poden processar diversos valors junts. NumPy té maquinària per triar els nuclis compatibles. El nostre temps d'execució informa de les característiques disponibles, però no traça les instruccions d'aquesta expressió. Atribuir tot el guany mesurat a les instruccions vectorials seria exagerar l'evidència.

2:40 El carret de la compra de la GPU pot romandre tancat. Hi ha alguna cosa profundament satisfactòria en una solució de rendiment que també cancel·la una compra. Malauradament, el benchmark continua.

### Quan desapareix l'impressionant augment de velocitat?

2:49 Amb vuit valors, la comprensió va guanyar. Cridar la maquinària de l'array va costar més que la petita feina. Els arrays grans ja preparats van prendre avantatge. Vam utilitzar proves repetides i un procés escalfat. Les versions més noves de Python poden canviar el punt d'encreuament. Després canviar el que l'aplicació necessita. Comenceu amb una llista de Python i acabeu amb una nova llista de Python. NumPy ha de convertir l'entrada en un array i convertir la resposta de nou en objectes

3:11 de Python. Aquests passos pertanyen a la factura si la vostra aplicació els necessita. Amb un milió de valors, aquest camí complet va trigar uns vint-i-vuit mil·lisegons. La comprensió també va trigar uns vint-i-vuit. El nostre avantatge dramàtic es va convertir en un gairebé empat. La part ràpida era real. L'avantatge depenia de permetre que les dades es mantinguessin en la seva forma numèrica.

### Quins límits pertanyen al benchmark?

3:28 Seguiu les dades. Si la següent operació accepta un array, conserveu l'array. Si convertiu repetidament entre llistes i arrays, mesureu aquests encreuaments. Aturar-se abans d'un lliurament car dóna números precisos per a la pregunta equivocada. Multiplicar aquest array crea un resultat temporal. Afegir els valors originals crea la sortida. L'execució nativa encara necessita memòria i mou dades.

3:47 Algunes operacions accepten un buffer de sortida, reduint les assignacions quan el vostre codi pot reutilitzar-lo de forma segura. Una línia bonica pot ordenar diversos buffers grans. Python Speed també assenyala aquest problema. L'assignador és notablement indiferent a la vostra estètica.

### Un bucle Python compilat també pot ser ràpid?

4:00 També podeu mantenir la sintaxi del bucle i canviar la seva execució. Numba pot compilar funcions numèriques de Python compatibles en codi natiu. Aquí teniu el bucle de la nostra prova amb el seu decorador de compilador. Encara diu for. El costós camí de l'intèrpret ha canviat. Després de la compilació, aquest bucle va trigar menys de mig mil·lisegon amb arrays preparats. La compilació en si va trigar aproximadament un segon en aquesta execució. Aquest cost de configuració es va excloure dels temps repetits,

4:22 de manera que una petita feina única mereix una comparació diferent. La pròpia guia de Numba està encantada de mostrar bucles explícits. Iniciar una migració de llenguatge abans de trobar el camí calent és una manera elaborada de evitar obrir un profiler. Primer trobeu el que consumeix el temps. Les esperes de xarxa, l'anàlisi d'objectes i l'aritmètica massiva requereixen diferents solucions. Les operacions d'array natives ajuden quan el càlcul i les dades encaixen.

4:43 Mesureu el resultat que el vostre cridador realment necessita. Ara per aquella drecera. Teniu una funció de Python i voleu que accepti un array. Un embolcall anomenat vectorize sona com el botó de rendiment que falta. La seva documentació té una frase important esperant.

### Què executa realment np.vectorize?

4:56 NumPy diu que el seu embolcall vectorize es proporciona principalment per conveniència. La seva implementació és essencialment un bucle for. L'embolcall accepta lots, però segueix cridant la vostra funció de Python per a elements successius. La interfície es va fer més curta. El límit d'execució va romandre ocupat. Vegeu com tornen els mateixos valors a través del callback de Python. Amb arrays preparats, aquesta versió va trigar uns vuitanta-set mil·lisegons. Va ser més lent que la nostra comprensió.

5:18 Un útil embolcall de broadcasting pot preservar el treball exacte per element que estava intentant eliminar. Comproveu la implementació darrere d'una interfície de lot, mantingueu les dades compatibles en la seva forma útil, i incloeu la conversió en la comparació. Els bucles natius, de callback i compilats poden semblar similars des de la posició de la persona que crida. El nom vectorize va fer una promesa que el vostre cronòmetre mai va signar. Mantingueu-lo quan la conveniència sigui el que necessiteu. Per al rendiment, comproveu el bucle que s'executa.

### Què hauries de canviar en el teu codi?

5:41 El meu veredicte és SHIP IT per processar un camí numèric calent mesurat. Mantingueu els bucles ordinaris quan ja funcionen bé. Comproveu on es produeix el treball i què necessita el següent cridador. Subscriu-te, prem la campana i digues-me als comentaris si l'hauries classificat diferentment. I aquesta és la diferència d'avui. Sóc en Niko d'Axrisi. Fusiona responsablement.

## Fonts

- [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
