Hugging Face publicó una guía práctica para principiantes sobre torch.profiler que enseña a leer trazas y a identificar por qué una operación pequeña gasta 2.314 ms de CPU frente a 23.104 µs de GPU, es decir, que la ejecución está mayormente en la CPU (overhead‑bound) (según Hugging Face, 29/05/2026). Este es el dato central: si no sabés leer la traza, no podés optimizar y la guía entrega pasos claros para hacerlo sobre ejemplos desde una multiplicación 64×64 hasta 4096×4096.

¿Qué nos enseña la guía y por qué importa?

La pieza arranca con la operación más básica (matmul + add) y demuestra que con matrices de tamaño 64 la “Self CPU time total” es 2.314 ms y la “Self CUDA time total” 23.104 µs, un síntoma clásico de algoritmo overhead‑bound (según Hugging Face, 29/05/2026). Al aumentar a 4096 el perfil cambia: la GPU pasa a consumir milisegundos comparables a la CPU y la ejecución se vuelve compute‑bound, es decir, la GPU ya es el cuello de botella (según Hugging Face, 29/05/2026). Además, la guía muestra que un buen warmup reduce el ruido inicial: el primer paso suele ser mucho más lento por inicializaciones y heurísticas de cuBLAS, y después los pasos se equiparan (antes vs. después del warmup, según Hugging Face, 29/05/2026). Si llegaste hasta acá, tenés lo más difícil: saber cuándo aumentar el trabajo por llamada o dejar que la GPU haga el trabajo duro.

¿Y si trabajo desde Argentina o solo con celular?

Es legítima la pregunta: ¿esto me sirve si no tengo un A100 de 80 GB? La guía usa una NVIDIA A100‑SXM4‑80GB para reproducir trazas (según Hugging Face, 29/05/2026), pero el aprendizaje principal es portátil: reconocer patrones de “gap” entre registro y dispatch, identificar cudaOccupancyMaxActiveBlocksPerMultiprocessor antes de kernels pesados, y comprobar si los pasos están dominados por sincronizaciones como cudaDeviceSynchronize. Para quienes trabajan con recursos limitados recomendamos empezar con profiling en CPU, usar batch pequeño‑a‑grande y herramientas gratuitas como Perfetto y la exportación JSON del profiler; es mobile‑first en el sentido de priorizar alternativas que se puedan ejecutar o simular en dispositivos comunes antes de depender de un clúster caro. Si esto te parece técnico, la alternativa honesta es probar con Google Colab (instancia gratuita con GPU limitada) o reproducir las conclusiones con tensores más pequeños: el patrón overhead → compute aparece igual, solo que en distinta escala.

¿Conviene usar torch.compile ahora mismo?

La guía da una respuesta matizada: torch.compile (Inductor) puede capturar regiones y reescribir add(matmul(…)) como aten::addmm, pero eso es fusión a nivel dispatcher, no necesariamente una única invocación de kernel sin copias. En el ejemplo 4096×4096 el código compilado sigue lanzando una copia Device‑to‑Device antes del GEMM —es decir, memoria extra— y la compilación aumenta el coste CPU por paso (ejemplo: de 0.1 ms a 0.2 ms en un paso, ~2× más) (según Hugging Face, 29/05/2026). Conclusión práctica: si tu modelo tiene docenas de ops y cada llamada agrupa mucho trabajo, torch.compile amortiza ese coste; si tenés operaciones pequeñas y muchas llamadas, la sobrecarga por llamada puede empeorar el rendimiento. Recomendamos medir: usar torch.profiler con y sin compile, aplicar warmup, y comparar trazas antes/después; si la CPU por paso baja en promedio tras compilar y no aumentan copias innecesarias, conviene dejarlo.

Cierre práctico: aprender a leer la tabla del profiler y la traza (CPU lane, GPU lane, gaps, occupancy queries) te ahorra horas de pruebas a ciegas. Empezá por el ejemplo más simple, hacé warmup, aumentá la carga por llamada y solo entonces probá torch.compile: son pasos verificables que te permiten decidir si la herramienta te ahorra tiempo real o solo te complica la vida.