{"id":35901,"date":"2026-05-27T12:51:52","date_gmt":"2026-05-27T10:51:52","guid":{"rendered":"https:\/\/inlab.fib.upc.edu\/noticias\/finetuning-de-un-llm-con-contexto-largo-en-una-gpu-de-16-gb"},"modified":"2026-05-29T13:26:38","modified_gmt":"2026-05-29T11:26:38","slug":"finetuning-de-un-llm-con-contexto-largo-en-una-gpu-de-16-gb","status":"publish","type":"post","link":"https:\/\/inlab.fib.upc.edu\/es\/articulos\/finetuning-de-un-llm-con-contexto-largo-en-una-gpu-de-16-gb","title":{"rendered":"Finetuning de un LLM con contexto largo en una GPU de 16 GB"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"35901\" class=\"elementor elementor-35901 elementor-35880\" data-elementor-post-type=\"post\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1896dc1 e-flex e-con-boxed e-con e-parent\" data-id=\"1896dc1\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-185712d exad-sticky-section-no exad-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"185712d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>Combinando cuantizaci\u00f3n, LoRA, FlashAttention-2 y otras optimizaciones para el fine-tuning de modelos LLM en una GPU de consumo.<\/p><p>El entrenamiento de grandes modelos del lenguaje (LLM) modernos est\u00e1 fuertemente limitado por la memoria de la GPU. Aunque los modelos recientes suelen asumir acceso a aceleradores empresariales con entre 40 y 80 GB de VRAM, muchos entornos de investigaci\u00f3n e ingenier\u00eda dependen de hardware de consumo con l\u00edmites significativamente m\u00e1s bajos. <\/p><p>En un proyecto reciente en el inLab FIB, exploramos el fine-tuning de modelos peque\u00f1os (de cuatro a ocho mil millones de par\u00e1metros) como Qwen3-8B, utilizando una \u00fanica NVIDIA GeForce RTX 4080 con 16 GB de VRAM. El objetivo era la generaci\u00f3n de memorias de subvenciones (proyecto <a href=\"https:\/\/inlab.fib.upc.edu\/es\/proyecto\/fabrai-copilot\">FabAI Copilot<\/a>) que requieren contextos de hasta 140.000 tokens, respetando al mismo tiempo las limitaciones del hardware de consumo. <\/p><p>Conseguirlo no fue posible mediante una \u00fanica t\u00e9cnica de optimizaci\u00f3n. En cambio, el flujo de trabajo de entrenamiento combin\u00f3 diversas estrategias que apuntaban simult\u00e1neamente a diferentes fuentes de consumo de VRAM. <\/p><h5><strong>Qu\u00e9 pasa con la VRAM durante el entrenamiento?<\/strong><\/h5><p>Una idea err\u00f3nea com\u00fan es que los pesos del modelo son el \u00fanico contribuyente principal al uso de la memoria de la GPU. En la pr\u00e1ctica, la memoria de entrenamiento se distribuye entre varios componentes: <\/p><h5> <\/h5>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-30451dc e-flex e-con-boxed e-con e-parent\" data-id=\"30451dc\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-c121f0c exad-sticky-section-no exad-glass-effect-no elementor-widget elementor-widget-image\" data-id=\"c121f0c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"800\" height=\"108\" src=\"https:\/\/inlab.fib.upc.edu\/wp-content\/uploads\/2026\/05\/article_jaume_1-1024x138.png\" class=\"attachment-large size-large wp-image-35888\" alt=\"\" srcset=\"https:\/\/inlab.fib.upc.edu\/wp-content\/uploads\/2026\/05\/article_jaume_1-1024x138.png 1024w, https:\/\/inlab.fib.upc.edu\/wp-content\/uploads\/2026\/05\/article_jaume_1-300x40.png 300w, https:\/\/inlab.fib.upc.edu\/wp-content\/uploads\/2026\/05\/article_jaume_1-768x103.png 768w, https:\/\/inlab.fib.upc.edu\/wp-content\/uploads\/2026\/05\/article_jaume_1.png 1205w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-ba8c643 e-flex e-con-boxed e-con e-parent\" data-id=\"ba8c643\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1516581 exad-sticky-section-no exad-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"1516581\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>El finetuning para contextos largos es especialmente exigente porque la memoria de activaci\u00f3n y los c\u00e1lculos de atenci\u00f3n crecen r\u00e1pidamente con la longitud de la secuencia. Incluso cuando los pesos del modelo caben en memoria, el entrenamiento de secuencias largas puede provocar errores de falta de memoria (Out-Of-Memory, OOM) \u00fanicamente a causa de las activaciones. <\/p><p>Reducci\u00f3n de la memoria del modelo<\/p><p>La primera capa de optimizaci\u00f3n se centr\u00f3 en reducir la huella de memoria persistente del modelo y de los estados de entrenamiento.<\/p><h5><strong>Cuantitzaci\u00f3n a 4-bit<\/strong><\/h5><p>La primera optimizaci\u00f3n fue utilizar los pesos del modelo cuantizados con el formato NF4 propio de la librer\u00eda BitsAndBytes. Esta optimizaci\u00f3n se realiza desde el principio, ya que normalmente los par\u00e1metros del modelo se publican en distintos niveles de precisi\u00f3n, permitiendo a los usuarios elegir entre la capacidad del modelo y la memoria ocupada. Habitualmente, las cuantizaciones est\u00e1n disponibles desde 1 bit hasta 16 bits, siendo la versi\u00f3n de 4 bits la elegida, cuatro veces m\u00e1s peque\u00f1a que la original y ofreciendo un buen compromiso de capacidad.  <\/p><h5><strong>LoRA, RS-LoRA y QLoRA<\/strong><\/h5><p>Low-Rank Adaptation (LoRA) reduce el n\u00famero de par\u00e1metros entrenables introduciendo peque\u00f1as matrices en cada capa del modelo. En la pr\u00e1ctica, la modificaci\u00f3n de todos los par\u00e1metros a menudo es inviable no por los propios pesos, sino porque los gradientes y los estados del optimizador escalan con el n\u00famero de par\u00e1metros. <\/p><p>Se utiliz\u00f3 Rank-Stabilized LoRA (RS-LoRA) y Quantized LoRA (QLoRA) aplicados a todas las proyecciones lineales para mejorar la estabilidad y poder entrenar con cuantizaciones m\u00e1s bajas.<\/p><h5><strong>Optimizando el optimizador<\/strong><\/h5><p>Los estados del optimizador pueden consumir cantidades enormes de memoria durante el entrenamiento y, en ocasiones, superan la memoria que requiere el propio modelo. Para mitigarlo, durante el entrenamiento se utilizaron optimizadores cuantizados de 8 bits junto con optimizadores con paginaci\u00f3n (paged_adamw_8bit). <\/p><p>Los optimizadores con paginaci\u00f3n descargan din\u00e1micamente los estados del optimizador a la RAM del sistema durante los picos de memoria, evitando errores de agotamiento de memoria (OOM) durante el entrenamiento de contextos largos. En la pr\u00e1ctica, esto fue especialmente importante durante el entrenamiento cerca de los l\u00edmites de hardware de la RTX 4080. <\/p><h5><strong>Control de la memoria de activaci\u00f3n<\/strong><\/h5><p>Aunque la cuantizaci\u00f3n y LoRA redujeron el uso de memoria est\u00e1tica, el entrenamiento con contextos largos segu\u00eda estando dominado por la memoria de activaci\u00f3n (activation memory). Por tanto, fueron necesarias diversas optimizaciones adicionales para controlar el crecimiento de los tensores intermedios durante el forward y backward pass. <\/p><h5><strong>FlashAttention-2<\/strong><\/h5><p>FlashAttention-2 implementa kernels que ejecutan las funciones de \u201catenci\u00f3n\u201d que requieren las capas Transformer teniendo en cuenta el tr\u00e1fico de datos, lo que minimiza el uso de VRAM mediante la agrupaci\u00f3n eficiente de los c\u00e1lculos de atenci\u00f3n.<\/p><p>Sin n\u00facleos de atenci\u00f3n optimizados, las ejecuciones de contextos largos a menudo superaban los l\u00edmites de memoria debido al comportamiento de escala cuadr\u00e1tica de la atenci\u00f3n en la arquitectura Transformer.<\/p><h5><strong>Gradient Checkpointing<\/strong><\/h5><p>El gradient checkpointing reduce la memoria de activaci\u00f3n descartando algunas activaciones durante el forward pass y recalcul\u00e1ndolas durante el paso inverso en lugar de almacenarlas permanentemente.<\/p><p>Esto introduce un cl\u00e1sico compromiso de ingenier\u00eda: un menor uso de memoria a costa de un mayor tiempo de c\u00e1lculo. No obstante, para contextos largos, la recomputaci\u00f3n de activaciones se volvi\u00f3 esencial para mantenerse dentro del presupuesto de 16 GB de VRAM. <\/p><h5> <\/h5>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-44a3146 e-flex e-con-boxed e-con e-parent\" data-id=\"44a3146\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-51bbd0c exad-sticky-section-no exad-glass-effect-no elementor-widget elementor-widget-image\" data-id=\"51bbd0c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"800\" height=\"684\" src=\"https:\/\/inlab.fib.upc.edu\/wp-content\/uploads\/2026\/05\/article_jaume_2.png\" class=\"attachment-large size-large wp-image-35891\" alt=\"\" srcset=\"https:\/\/inlab.fib.upc.edu\/wp-content\/uploads\/2026\/05\/article_jaume_2.png 874w, https:\/\/inlab.fib.upc.edu\/wp-content\/uploads\/2026\/05\/article_jaume_2-300x256.png 300w, https:\/\/inlab.fib.upc.edu\/wp-content\/uploads\/2026\/05\/article_jaume_2-768x656.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-e15e7d2 e-flex e-con-boxed e-con e-parent\" data-id=\"e15e7d2\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-eef70b5 exad-sticky-section-no exad-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"eef70b5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<h5><strong>Kernel Fusion<\/strong><\/h5><p>El entrenamiento tambi\u00e9n utiliz\u00f3 kernels Triton fusionados a trav\u00e9s del framework Unsloth. Estos n\u00facleos combinan operaciones adyacentes, de forma similar a como funciona FlashAttention, en menos operaciones de GPU. <\/p><p>La reducci\u00f3n de la materializaci\u00f3n de tensores intermedios ayud\u00f3 a disminuir la sobrecarga de activaci\u00f3n y a mejorar el rendimiento. En la pr\u00e1ctica, sin embargo, los kernels propios de Unsloth no son compatibles con los de Liger-Kernel, lo que obligaba a hacer concesiones entre ambas optimizaciones. <\/p><h5><strong>Acumulaci\u00f3n de Gradientes<\/strong><\/h5><p>Para controlar a\u00fan m\u00e1s el pico de uso de la VRAM, el proceso de entrenamiento utiliz\u00f3 solo una secuencia en cada forward y backward pass, pero en lugar de limitarse a realizar una actualizaci\u00f3n del optimizador con un solo ejemplo (lo que puede dar lugar a overfitting), se combin\u00f3 con la acumulaci\u00f3n de gradientes (Gradient Accumulation).<\/p><p>Concretamente, en lugar de actualizar los par\u00e1metros del modelo despu\u00e9s de procesar cada secuencia, los gradientes se calculan de forma incremental y se acumulan en memoria a lo largo de varios pasos, actualizando los pesos con una \u201cdirecci\u00f3n\u201d m\u00e1s precisa.<\/p><h5><strong>Gesti\u00f3n de contextos largos<\/strong><\/h5><p>M\u00e9s enll\u00e0 de les t\u00e8cniques est\u00e0ndard d&#8217;optimitzaci\u00f3 de LLM, el projecte tamb\u00e9 va requerir estrat\u00e8gies expl\u00edcites de gesti\u00f3 de context per donar suport a les c\u00e0rregues de treball de generaci\u00f3 de documents llargs.<\/p><h5><strong>Smart Context Truncation<\/strong><\/h5><p>Se implement\u00f3 un algoritmo de truncamiento de decaimiento exponencial para mantener una longitud de contexto m\u00e1xima de 20.000 tokens en cada paso, priorizando la informaci\u00f3n reciente.<\/p><p>Aunque el documento completo puede acabar teniendo m\u00e1s de 140.000 tokens de longitud, si dividimos inteligentemente este documento, podemos abordar cada secci\u00f3n individualmente y ser mucho m\u00e1s estrictos con el contexto utilizado en cada paso. Esto tambi\u00e9n puede considerarse una optimizaci\u00f3n que ofrece una reducci\u00f3n de memoria a cambio de m\u00e1s tiempo de ejecuci\u00f3n y cierta p\u00e9rdida de contexto en algunos casos. <\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-44c53cc exad-sticky-section-no exad-glass-effect-no elementor-widget elementor-widget-image\" data-id=\"44c53cc\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"426\" height=\"235\" src=\"https:\/\/inlab.fib.upc.edu\/wp-content\/uploads\/2026\/05\/article_jaume_3.png\" class=\"attachment-large size-large wp-image-35894\" alt=\"\" srcset=\"https:\/\/inlab.fib.upc.edu\/wp-content\/uploads\/2026\/05\/article_jaume_3.png 426w, https:\/\/inlab.fib.upc.edu\/wp-content\/uploads\/2026\/05\/article_jaume_3-300x165.png 300w\" sizes=\"(max-width: 426px) 100vw, 426px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-ee0825f e-flex e-con-boxed e-con e-parent\" data-id=\"ee0825f\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-579b14a exad-sticky-section-no exad-glass-effect-no elementor-widget elementor-widget-text-editor\" data-id=\"579b14a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<h5><strong>Vocabulary Slicing<\/strong><\/h5><p>Una optimizaci\u00f3n especialmente eficaz consisti\u00f3 en reducir el tama\u00f1o del vocabulario del tokenizador y del modelo de 128k tokens a unos 100k. Esto redujo la memoria necesaria tanto para las capas de embedding como para la capa final del modelo. <\/p><p>Aunque se habla menos de ello que de la cuantizaci\u00f3n o LoRA, la reducci\u00f3n del vocabulario result\u00f3 ser una optimizaci\u00f3n de nivel de sistema sorprendentemente eficaz bajo estrictas limitaciones de VRAM. Esta reducci\u00f3n es muy efectiva si el LLM final va a funcionar exclusivamente en un conjunto cerrado de idiomas, ya que se pueden eliminar muchos tokens sin impacto en el rendimiento. <\/p><h5><strong>Conclusi\u00f3n<\/strong><\/h5><p>El resultado m\u00e1s importante de este trabajo no fue solo la capacidad de realizar el fine-tuning del LLM, sino tambi\u00e9n la cantidad de conocimiento de ingenier\u00eda que surgi\u00f3 de tener que trabajar dentro de este espacio de restricciones.<\/p><p>Trabajar bajo l\u00edmites estrictos de VRAM cambi\u00f3 fundamentalmente la forma de abordar cada problema. En lugar de confiar en configuraciones de entrenamiento por defecto, cada etapa y cada par\u00e1metro de configuraci\u00f3n tuvo que cuestionarse, medirse y simplificarse hasta que fuera viable. <\/p><p>Las restricciones no solo dieron forma a la soluci\u00f3n, sino tambi\u00e9n al propio proceso de aprendizaje.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Combinando cuantizaci\u00f3n, LoRA, FlashAttention-2 y otras optimizaciones para el fine-tuning de modelos LLM en una GPU de consumo. El entrenamiento de grandes modelos del lenguaje (LLM) modernos est\u00e1 fuertemente limitado por la memoria de la GPU. Aunque los modelos recientes suelen asumir acceso a aceleradores empresariales con entre 40 y 80 GB de VRAM, muchos [&hellip;]<\/p>\n","protected":false},"author":1302,"featured_media":35900,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[496],"tags":[],"experteses":[],"class_list":["post-35901","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-articulos"],"acf":[],"_links":{"self":[{"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/posts\/35901","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/users\/1302"}],"replies":[{"embeddable":true,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/comments?post=35901"}],"version-history":[{"count":1,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/posts\/35901\/revisions"}],"predecessor-version":[{"id":35902,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/posts\/35901\/revisions\/35902"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/media\/35900"}],"wp:attachment":[{"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/media?parent=35901"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/categories?post=35901"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/tags?post=35901"},{"taxonomy":"experteses","embeddable":true,"href":"https:\/\/inlab.fib.upc.edu\/es\/wp-json\/wp\/v2\/experteses?post=35901"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}