{"schemaVersion":1,"id":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared","title":"Comparación de Cuantización de LLMs: GPTQ, AWQ, GGUF y SqueezeLLM","description":"Una comparación práctica de métodos de cuantización de LLMs con benchmarks reales de perplejidad, uso de memoria y velocidad de inferencia. Cuándo usar cada método, y los casos donde 4-bit supera a 8-bit.","language":"es","datePublished":"2025-10-11","dateModified":null,"contentFormat":"text/markdown","content":"AI/ML\n\n# Comparación de Cuantización de LLMs: GPTQ, AWQ, GGUF y SqueezeLLM\n\n2025-10-1110 min lectura\n\nLucio Durán\nEngineering Manager & AI Solutions Architect\n\nTambién disponible en: [English](<https://lucioduran.com/blog/llm-quantization-gptq-awq-gguf-compared>)\n\n## El Problema Central\n\nUn modelo de 7B parámetros en FP16 (la precisión estándar de entrenamiento) toma ~14GB de VRAM. Eso es una RTX 4090 completa, o más de lo que tiene una MacBook Air M2. Escalá a 70B y se necesita 140GB, múltiples A100.\n\nLa cuantización comprime los pese es de floats de 16-bit a menor precisión (8-bit, 4-bit, a veces 3-bit o hasta 2-bit). La pregunta no es si cuantizar, para inferencia, casi seguro que deberías. La pregunta es *cómo*, porque los métodos difieren de maneras que afectan calidad, velocidad y compatibilidad.\n\n## Método 1: GPTQ (Cuantización Post-Training vía Optimal Brain Surgeon)\n\nGPTQ fue el primer método que hizo práctica la cuantización a 4-bit para modelos grandes. Está basado en un insight matemático inteligente: en vez de cuantizar cada peso independientemente (que es lo que hace el naive round-to-nearest), GPTQ cuantiza una columna de la matriz de pese es a la vez y ajusta las columnas restantes para compensar el error de cuantización.\n\nEl algoritmo, simplificado:\n\n```python\n# Pseudocódigo para cuantización GPTQ de una capa lineal\ndef gptq_quantize(W, H, bits=4, group_size=128):\n \"\"\"\n W: matriz de pese es [out_features, in_features]\n H: aproximación Hessiana (X^T @ X de datos de calibración)\n \"\"\"\n Q = torch.zeros_like(W)\n Err = torch.zeros_like(W)\n\n # Procesar columnas de izquierda a derecha\n for col in range(W.shape[1]):\n # Cuantizar esta columna\n q = quantize_to_grid(W[:, col], bits, group_size)\n Q[:, col] = q\n\n # Computar error de cuantizar esta columna\n err = (W[:, col] - q) / H[col, col]\n\n # Compensar: ajustar columnas no cuantizadas restantes\n W[:, col+1:] -= err.unsqueeze(1) @ H[col, col+1:].unsqueeze(0)\n\n return Q\n```\n\nLa matriz Hessiana ` H ` se computa de un set de calibración pequeño (típicamente 128 muestras de C4 o WikiText). Esta es la clave, GPTQ usa información de segundo orden sobre cómo la landscape de loss curva alrededor de cada peso, tomando decisiones de cuantización más inteligentes que el redondeo simple.\n\n**Pros:**\n\n- Excelente calidad para inferencia GPU\n- Kernels CUDA ExLlama v2 proveen la inferencia batcheada más rápida\n- Ecosistema maduro (AutoGPTQ, integración con transformers)\n\n**Contras:**\n\n- Requiere GPU para cuantizar (el cómputo de la Hessiana es caro)\n- No es genial para inferencia CPU\n- La cuantización por grupo agrega complejidad al formato de pesos\n\n## Método 2: AWQ (Activation-Aware Weight Quantization)\n\nEl insight de AWQ es elegante: no todos los pese es son igual de importantes. Los pese es que multiplican activaciones grandes tienen más impacto en la calidad del output. Entonces en vez de tratar todos los pese es igual, AWQ encuentra los pese es \"salientes\" (los multiplicados por activaciones grandes) y los protege.\n\nEl truco es que AWQ no mantiene los pese es salientes a mayor precisión. En cambio, aplica un factor de escala por canal antes de la cuantización que distribuye el rango de los pese es salientes a través de más bins de cuantización:\n\n```python\n# El insight central de AWQ\ndef awq_scale_weights(W, activations, alpha=0.5):\n \"\"\"\n Escalar pese es basándose en magnitudes de activación antes de cuantizar.\n Esto protege pese es importantes dándoles más bins de cuantización.\n \"\"\"\n # Computar magnitudes de activación por canal\n act_scales = activations.abs().mean(dim=0)\n\n # Factor de escala: canales con activaciones más grandes se escalan hacia arriba\n # antes de cuantización (más bins), y se escalan de vuelta en runtime\n scales = act_scales.pow(alpha)\n\n # Aplicar: W_scaled = W * diag(scales)\n # Después de cuantización: W_q * diag(1/scales) ≈ W\n W_scaled = W * scales.unsqueeze(0)\n\n return W_scaled, scales\n```\n\nLo lindo es que el escalado es matemáticamente equivalente, escalás antes de cuantizar y des-escalás en runtime, así que el output fp16 es el mismo. Pero la representación cuantizada es más precisa porque más bits se asignan a los pese es que más importan.\n\n**Benchmarks, LLaMA-2 7B, perplexity WikiText-2 (menor es mejor):**\n\n| Método | PPL 4-bit | PPL 3-bit | Memoria | Tiempo quant |\n| --- | --- | --- | --- | --- |\n| FP16 (baseline) | 5.47 | , | 13.5GB | , |\n| GPTQ 4-bit g128 | 5.63 | 6.29 | 3.9GB | 12min |\n| AWQ 4-bit g128 | 5.60 | 6.14 | 3.9GB | 8min |\n| Round-to-nearest | 6.12 | 8.45 | 3.9GB | 2min |\n\nAWQ consistentemente supera a GPTQ en calidad, especialmente a 3-bit. Pero GPTQ con kernels ExLlama es más rápido en inferencia. Elegir tu prioridad.\n\n## Método 3: GGUF (El Formato de llama.cpp)\n\nGGUF no es un algoritmo de cuantización, es un formato de archivo y ecosistema. llama.cpp implementa varios métodos de cuantización bajo el paraguas GGUF, y la convención de nombres es inicialmente confusa:\n\n- **Q4\\_0**: Cuantización simple de 4-bit con bloques de 32 pesos, una escala por bloque\n- **Q4\\_1**: Q4\\_0 + valor mínimo por bloque (efectivamente un offset)\n- **Q4\\_K\\_S**: K-quant small, usa métricas de importancia para variar precisión por tensor\n- **Q4\\_K\\_M**: K-quant medium, más tensores reciben tratamiento de 5-bit\n- **Q5\\_K\\_M**: K-quant medium en base 5-bit\n- **Q8\\_0**: Cuantización de 8-bit (buen baseline, casi sin pérdida)\n\nLos K-quants son los interesantes. Usan una heurística: las capas de proyección de atención (matrices Q, K, V, O) son más sensibles al error de cuantización que las capas FFN. Entonces Q4\\_K\\_M cuantiza capas de atención a 5-bit manteniendo FFN a 4-bit:\n\n```bash\n# Cuantizando con llama.cpp\n./llama-quantize input-model-f16.gguf output-q4km.gguf Q4_K_M\n\n# El output te dice exactamente qué pasó:\n# [ 1/291] layers.0.attention.wq.weight - [4096, 4096] -> Q5_K (5.5 bpw)\n# [ 2/291] layers.0.attention.wk.weight - [4096, 4096] -> Q5_K (5.5 bpw)\n# [ 3/291] layers.0.attention.wv.weight - [4096, 4096] -> Q5_K (5.5 bpw)\n# [ 4/291] layers.0.ffn_gate.weight - [4096, 11008] -> Q4_K (4.5 bpw)\n# [ 5/291] layers.0.ffn_up.weight - [4096, 11008] -> Q4_K (4.5 bpw)\n# [ 6/291] layers.0.ffn_down.weight - [11008, 4096] -> Q4_K (4.5 bpw)\n```\n\nEl approach de precisión mixta significa que Q4\\_K\\_M promedia aproximadamente 4.85 bits por peso, ligeramente más que 4-bit puro pero mediblemente mejor en calidad.\n\n**Por qué GGUF gana para inferencia local:**\n\n1. **Híbrido CPU+GPU**: llama.cpp puede repartir capas entre CPU y GPU. ¿Teners una laptop con 8GB de VRAM y 32GB de RAM? Colocar 20 capas en GPU y 12 en CPU.\n2. **Carga memory-mapped**: El archivo del modelo se hace ` mmap `, así que cargar un modelo de 4GB toma milisegundos (el OS pagina datos según se necesita).\n3. **Optimizado para Apple Silicon**: Shaders Metal para GPUs M-series usan memoria unificada eficientemente.\n4. **Sin dependencia de Python**: El servidor de inferencia es C++ puro. Deployar es copiar un binario y un archivo de modelo.\n\n## Método 4: SqueezeLLM\n\nSqueezeLLM es el método que recibe comparativamente poca atención, lo cual es discutiblemente un error. Hace algo fundamentalmente diferente a los otros tres: separa los pese es en un componente cuantizado \"denso\" y una matriz de corrección \"esparsa\":\n\n```\nW ≈ W_cuantizado + S (corrección esparsa)\n```\n\nLa matriz esparsa ` S ` contiene correcciones para los pese es donde el error de cuantización es más alto (los outliers). Estos outliers son típicamente \\<0.5% de todos los pesos, así que ` S ` es extremadamente esparsa y agrega overhead de memoria mínimo.\n\nEl resultado es llamativo: SqueezeLLM a 4-bit logra calidad muy cercana a métodos de 8-bit, con uso de memoria cercano a otros métodos de 4-bit.\n\n| Método | PPL 4-bit (LLaMA-2 7B) | Memoria | Notas |\n| --- | --- | --- | --- |\n| GPTQ | 5.63 | 3.9GB | g128 |\n| AWQ | 5.60 | 3.9GB | g128 |\n| GGUF Q4\\_K\\_M | 5.68 | 4.1GB | Precisión mixta |\n| SqueezeLLM | 5.54 | 4.3GB | Denso + esparso |\n| FP16 | 5.47 | 13.5GB | Baseline |\n\nEl 5.54 de SqueezeLLM está solo 0.07 por encima de FP16, eso es esencialmente sin pérdida para propósitos prácticos. Los 400MB extra de memoria vienen de la matriz de corrección esparsa.\n\n**La contra:** La inferencia de SqueezeLLM requiere kernels CUDA custom para la descomposición esparsa-densa, y el soporte del ecosistema es mínimo. Vas a estar escribiendo tu propio código de serving. Para research o herramientas internas, vale la pena. Para serving de producción a escala, la madurez del ecosistema de GPTQ/AWQ/GGUF gana.\n\n## Velocidad de Inferencia Real\n\nLos cuatro métodos se corrieron en el mismo hardware con prompts idénticos (512 tokens de input, 256 de output), usando el mejor engine de inferencia disponible para cada método:\n\n**NVIDIA RTX 4090 (24GB VRAM):**\n\n| Método | Engine | 7B tok/s | 13B tok/s | 70B\\* |\n| --- | --- | --- | --- | --- |\n| GPTQ 4-bit | ExLlama v2 | 142 | 88 | 18 |\n| AWQ 4-bit | AutoAWQ | 128 | 79 | 16 |\n| GGUF Q4\\_K\\_M | llama.cpp CUDA | 118 | 72 | 15 |\n| SqueezeLLM 4-bit | CUDA custom | 95 | 54 | , |\n| FP16 | vLLM | 89 | OOM | OOM |\n\n\\*70B requiere offloading a RAM de CPU para todos los métodos de 4-bit en una sola 4090.\n\n**Apple M3 Pro (18GB memoria unificada):**\n\n| Método | Engine | 7B tok/s | 13B tok/s |\n| --- | --- | --- | --- |\n| GGUF Q4\\_K\\_M | llama.cpp Metal | 52 | 34 |\n| GGUF Q4\\_0 | llama.cpp Metal | 58 | 37 |\n| MLX 4-bit | mlx-lm | 47 | 29 |\n\nGGUF domina en Apple Silicon. El backend Metal en llama.cpp está bien optimizado para la arquitectura de memoria de la serie M.\n\n## La Matriz de Decisión\n\nDespués de una evaluación extensiva, aquí va un framework de decisión práctico:\n\n**Escenario 1: Servidor GPU, inferencia batcheada, máximo throughput** → GPTQ 4-bit con kernels ExLlama v2 vía vLLM o text-generation-inference\n\n**Escenario 2: Inferencia local en tu laptop/desktop** → GGUF Q4\\_K\\_M con llama.cpp (híbrido CPU+GPU si es necesario)\n\n**Escenario 3: Deploy en edge, VRAM limitada, se necesita huella de modelo chica** → AWQ 4-bit (menor overhead de runtime, buen soporte de librerías)\n\n**Escenario 4: Máxima calidad, dispuesto a sacrificar algo de velocidad y conveniencia de ecosistema** → SqueezeLLM 4-bit (más cerca de calidad FP16 en memoria de 4-bit)\n\n**Escenario 5: No se está seguro y solo se desea algo que funcione** → GGUF Q4\\_K\\_M. verdad. Es el más portable, tiene la historia de deployment más simple, funciona en todas las plataformas, y la calidad está a un tiro de piedra de los métodos más complejos.\n\n## Hallazgos Notables\n\n**4-bit es mejor que 8-bit naive para muchas tareas.** Un modelo GPTQ 4-bit con calibración apropiada muchas veces supera a un modelo 8-bit simple de round-to-nearest. Los datos de calibración le dan al cuantizador información sobre qué pese es importan, y 4-bit + inteligencia supera a 8-bit + ignorancia.\n\n**Los datos de calibración son el hiperparámetro más subestimado.** Todas las guías dicen \"utilizar 128 muestras de C4.\" Si tu modelo está fine-tuned para generación de código y calibrás con prosa de Wikipedia, se está dejando calidad sobre la mesa. Crear sets de calibración específicos del dominio puede recuperar 0.2-0.4 puntos de perplexity en modelos especializados.\n\n**La cuantización y el KV cache interactúan.** Un modelo Q4 ahorra 70% en memoria de pesos, pero el KV cache sigue siendo FP16 por default. Con 32K de longitud de contexto con un modelo 7B, el KV cache solo son ~2GB. Investigá la cuantización de KV cache a FP8 (vLLM soporta esto) para obtener el beneficio completo.\n\nEl panorama de la cuantización se mueve rápido, para cuando leas esto, capaz haya un método nuevo que cambie el cálculo. Pero los principios no cambian: entendé qué se está intercambiando (precisión, velocidad, compatibilidad), medir con tus datos reales, y los benchmarks independientes sobre datos reales de producción siguen siendo la medida más confiable.\n\n## Preguntas frecuentes\n\n### ¿Qué método de cuantización debería usar para mi modelo de 7B parámetros?\n\nPara inferencia GPU con batching: GPTQ 4-bit con kernels ExLlama v2. Para inferencia local de un solo usuario: GGUF Q4\\_K\\_M con llama.cpp. Para deployment en edge con VRAM limitado: AWQ 4-bit. Para máxima calidad con compresión moderada: SqueezeLLM a 4-bit con descomposición densa-y-esparsa.\n\n### ¿Cuánta calidad pierdo con cuantización de 4-bit?\n\nEn un modelo LLaMA-2 7B, la perplexity FP16 en WikiText-2 es 5.47. GPTQ 4-bit da 5.63 (+0.16), AWQ 4-bit da 5.60 (+0.13), GGUF Q4\\_K\\_M da 5.68 (+0.21), y SqueezeLLM 4-bit da 5.54 (+0.07). Para la mayoría de las aplicaciones, estas diferencias son imperceptibles en la calidad del output.\n\n### ¿Puedo cuantizar y correr modelos en Apple Silicon?\n\nSí. GGUF con llama.cpp tiene el mejor soporte Metal, usa la memoria unificada de la GPU directamente. Para un modelo 13B en Q4\\_K\\_M, eliminars ~35 tok/s en un M3 Pro con 18GB de memoria unificada. MLX también soporta modelos cuantizados nativamente pero con un formato diferente (safetensors cuantizados de MLX).\n\n## Tips\n\n1. **El set de calibración de AWQ importa enormemente:** No utilizar el ` pile-uncopyrighted ` por defecto para modelos de dominio específico. Crear un set de calibración con datos reales de inferencia, incluso 128 muestras es suficiente. Se ha observado una caída de perplejidad de 0.3 en un modelo de QA médico solo cambiando los datos de calibración a abstracts de PubMed.\n2. **GGUF Q4\\_K\\_M es el punto óptimo para la mayoría de los casos:** Utiliza una mezcla de cuantización de 4-bit y 5-bit, con 5-bit para capas de atención y 4-bit para capas FFN. El flag de ` llama-quantize ` es ` --type q4_K_M `. Típicamente queda dentro de 0.1 de perplejidad de Q5\\_K\\_M con 20% menos de memoria.\n3. **Perfilar la VRAM con ` nvidia-smi dmon -s m ` durante inferencia:** Los modelos cuantizados pueden igualmente provocar OOM si el KV cache crece sin límite. Configurar ` max_seq_len ` explícitamente en la configuración de serving. Un modelo 7B en Q4 usa ~4GB para pesos pero el KV cache a 32K de contexto agrega otros 2GB. Es frecuente olvidar el cache.\n4. **Para inferencia en batch, GPTQ con kernel ` exllama_v2 ` supera a AWQ:** Los kernels CUDA personalizados de ExLlama v2 para dequantización GPTQ son más rápidos que los de AutoAWQ en batch sizes \\>4. Configurar ` disable_exllama=False ` en la configuración de cuantización y verificar que ` torch.cuda.is_bf16_supported() ` devuelva true para mejores resultados.\n\n- llm\n- cuantización\n- gptq\n- awq\n- gguf\n- optimización-inferencia\n\n[Volver al Blog](<https://lucioduran.com/es/blog>)","headings":[{"level":1,"text":"Comparación de Cuantización de LLMs: GPTQ, AWQ, GGUF y SqueezeLLM","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#title"},{"level":2,"text":"El Problema Central","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#el-problema-central"},{"level":2,"text":"Método 1: GPTQ (Cuantización Post-Training vía Optimal Brain Surgeon)","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#mtodo-1-gptq-cuantizacin-post-training-va-optimal-brain-surgeon"},{"level":2,"text":"Método 2: AWQ (Activation-Aware Weight Quantization)","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#mtodo-2-awq-activation-aware-weight-quantization"},{"level":2,"text":"Método 3: GGUF (El Formato de llama.cpp)","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#mtodo-3-gguf-el-formato-de-llamacpp"},{"level":2,"text":"Método 4: SqueezeLLM","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#mtodo-4-squeezellm"},{"level":2,"text":"Velocidad de Inferencia Real","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#velocidad-de-inferencia-real"},{"level":2,"text":"La Matriz de Decisión","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#la-matriz-de-decisin"},{"level":2,"text":"Hallazgos Notables","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#hallazgos-notables"},{"level":2,"text":"Preguntas frecuentes","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#questions"},{"level":3,"text":"¿Qué método de cuantización debería usar para mi modelo de 7B parámetros?","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#question-1"},{"level":3,"text":"¿Cuánta calidad pierdo con cuantización de 4-bit?","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#question-2"},{"level":3,"text":"¿Puedo cuantizar y correr modelos en Apple Silicon?","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#question-3"},{"level":2,"text":"Tips","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#article-tips"}],"sections":[{"heading":"Comparación de Cuantización de LLMs: GPTQ, AWQ, GGUF y SqueezeLLM","level":1,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared","content":"AI/ML"},{"heading":"Comparación de Cuantización de LLMs: GPTQ, AWQ, GGUF y SqueezeLLM","level":1,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#title","content":"2025-10-1110 min lectura\n\nLucio Durán\nEngineering Manager & AI Solutions Architect\n\nTambién disponible en: [English](<https://lucioduran.com/blog/llm-quantization-gptq-awq-gguf-compared>)"},{"heading":"El Problema Central","level":2,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#el-problema-central","content":"Un modelo de 7B parámetros en FP16 (la precisión estándar de entrenamiento) toma ~14GB de VRAM. Eso es una RTX 4090 completa, o más de lo que tiene una MacBook Air M2. Escalá a 70B y se necesita 140GB, múltiples A100.\n\nLa cuantización comprime los pese es de floats de 16-bit a menor precisión (8-bit, 4-bit, a veces 3-bit o hasta 2-bit). La pregunta no es si cuantizar, para inferencia, casi seguro que deberías. La pregunta es *cómo*, porque los métodos difieren de maneras que afectan calidad, velocidad y compatibilidad."},{"heading":"Método 1: GPTQ (Cuantización Post-Training vía Optimal Brain Surgeon)","level":2,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#mtodo-1-gptq-cuantizacin-post-training-va-optimal-brain-surgeon","content":"GPTQ fue el primer método que hizo práctica la cuantización a 4-bit para modelos grandes. Está basado en un insight matemático inteligente: en vez de cuantizar cada peso independientemente (que es lo que hace el naive round-to-nearest), GPTQ cuantiza una columna de la matriz de pese es a la vez y ajusta las columnas restantes para compensar el error de cuantización.\n\nEl algoritmo, simplificado:\n\n```python\n# Pseudocódigo para cuantización GPTQ de una capa lineal\ndef gptq_quantize(W, H, bits=4, group_size=128):\n \"\"\"\n W: matriz de pese es [out_features, in_features]\n H: aproximación Hessiana (X^T @ X de datos de calibración)\n \"\"\"\n Q = torch.zeros_like(W)\n Err = torch.zeros_like(W)\n\n # Procesar columnas de izquierda a derecha\n for col in range(W.shape[1]):\n # Cuantizar esta columna\n q = quantize_to_grid(W[:, col], bits, group_size)\n Q[:, col] = q\n\n # Computar error de cuantizar esta columna\n err = (W[:, col] - q) / H[col, col]\n\n # Compensar: ajustar columnas no cuantizadas restantes\n W[:, col+1:] -= err.unsqueeze(1) @ H[col, col+1:].unsqueeze(0)\n\n return Q\n```\n\nLa matriz Hessiana ` H ` se computa de un set de calibración pequeño (típicamente 128 muestras de C4 o WikiText). Esta es la clave, GPTQ usa información de segundo orden sobre cómo la landscape de loss curva alrededor de cada peso, tomando decisiones de cuantización más inteligentes que el redondeo simple.\n\n**Pros:**\n\n- Excelente calidad para inferencia GPU\n- Kernels CUDA ExLlama v2 proveen la inferencia batcheada más rápida\n- Ecosistema maduro (AutoGPTQ, integración con transformers)\n\n**Contras:**\n\n- Requiere GPU para cuantizar (el cómputo de la Hessiana es caro)\n- No es genial para inferencia CPU\n- La cuantización por grupo agrega complejidad al formato de pesos"},{"heading":"Método 2: AWQ (Activation-Aware Weight Quantization)","level":2,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#mtodo-2-awq-activation-aware-weight-quantization","content":"El insight de AWQ es elegante: no todos los pese es son igual de importantes. Los pese es que multiplican activaciones grandes tienen más impacto en la calidad del output. Entonces en vez de tratar todos los pese es igual, AWQ encuentra los pese es \"salientes\" (los multiplicados por activaciones grandes) y los protege.\n\nEl truco es que AWQ no mantiene los pese es salientes a mayor precisión. En cambio, aplica un factor de escala por canal antes de la cuantización que distribuye el rango de los pese es salientes a través de más bins de cuantización:\n\n```python\n# El insight central de AWQ\ndef awq_scale_weights(W, activations, alpha=0.5):\n \"\"\"\n Escalar pese es basándose en magnitudes de activación antes de cuantizar.\n Esto protege pese es importantes dándoles más bins de cuantización.\n \"\"\"\n # Computar magnitudes de activación por canal\n act_scales = activations.abs().mean(dim=0)\n\n # Factor de escala: canales con activaciones más grandes se escalan hacia arriba\n # antes de cuantización (más bins), y se escalan de vuelta en runtime\n scales = act_scales.pow(alpha)\n\n # Aplicar: W_scaled = W * diag(scales)\n # Después de cuantización: W_q * diag(1/scales) ≈ W\n W_scaled = W * scales.unsqueeze(0)\n\n return W_scaled, scales\n```\n\nLo lindo es que el escalado es matemáticamente equivalente, escalás antes de cuantizar y des-escalás en runtime, así que el output fp16 es el mismo. Pero la representación cuantizada es más precisa porque más bits se asignan a los pese es que más importan.\n\n**Benchmarks, LLaMA-2 7B, perplexity WikiText-2 (menor es mejor):**\n\n| Método | PPL 4-bit | PPL 3-bit | Memoria | Tiempo quant |\n| --- | --- | --- | --- | --- |\n| FP16 (baseline) | 5.47 | , | 13.5GB | , |\n| GPTQ 4-bit g128 | 5.63 | 6.29 | 3.9GB | 12min |\n| AWQ 4-bit g128 | 5.60 | 6.14 | 3.9GB | 8min |\n| Round-to-nearest | 6.12 | 8.45 | 3.9GB | 2min |\n\nAWQ consistentemente supera a GPTQ en calidad, especialmente a 3-bit. Pero GPTQ con kernels ExLlama es más rápido en inferencia. Elegir tu prioridad."},{"heading":"Método 3: GGUF (El Formato de llama.cpp)","level":2,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#mtodo-3-gguf-el-formato-de-llamacpp","content":"GGUF no es un algoritmo de cuantización, es un formato de archivo y ecosistema. llama.cpp implementa varios métodos de cuantización bajo el paraguas GGUF, y la convención de nombres es inicialmente confusa:\n\n- **Q4\\_0**: Cuantización simple de 4-bit con bloques de 32 pesos, una escala por bloque\n- **Q4\\_1**: Q4\\_0 + valor mínimo por bloque (efectivamente un offset)\n- **Q4\\_K\\_S**: K-quant small, usa métricas de importancia para variar precisión por tensor\n- **Q4\\_K\\_M**: K-quant medium, más tensores reciben tratamiento de 5-bit\n- **Q5\\_K\\_M**: K-quant medium en base 5-bit\n- **Q8\\_0**: Cuantización de 8-bit (buen baseline, casi sin pérdida)\n\nLos K-quants son los interesantes. Usan una heurística: las capas de proyección de atención (matrices Q, K, V, O) son más sensibles al error de cuantización que las capas FFN. Entonces Q4\\_K\\_M cuantiza capas de atención a 5-bit manteniendo FFN a 4-bit:\n\n```bash\n# Cuantizando con llama.cpp\n./llama-quantize input-model-f16.gguf output-q4km.gguf Q4_K_M\n\n# El output te dice exactamente qué pasó:\n# [ 1/291] layers.0.attention.wq.weight - [4096, 4096] -> Q5_K (5.5 bpw)\n# [ 2/291] layers.0.attention.wk.weight - [4096, 4096] -> Q5_K (5.5 bpw)\n# [ 3/291] layers.0.attention.wv.weight - [4096, 4096] -> Q5_K (5.5 bpw)\n# [ 4/291] layers.0.ffn_gate.weight - [4096, 11008] -> Q4_K (4.5 bpw)\n# [ 5/291] layers.0.ffn_up.weight - [4096, 11008] -> Q4_K (4.5 bpw)\n# [ 6/291] layers.0.ffn_down.weight - [11008, 4096] -> Q4_K (4.5 bpw)\n```\n\nEl approach de precisión mixta significa que Q4\\_K\\_M promedia aproximadamente 4.85 bits por peso, ligeramente más que 4-bit puro pero mediblemente mejor en calidad.\n\n**Por qué GGUF gana para inferencia local:**\n\n1. **Híbrido CPU+GPU**: llama.cpp puede repartir capas entre CPU y GPU. ¿Teners una laptop con 8GB de VRAM y 32GB de RAM? Colocar 20 capas en GPU y 12 en CPU.\n2. **Carga memory-mapped**: El archivo del modelo se hace ` mmap `, así que cargar un modelo de 4GB toma milisegundos (el OS pagina datos según se necesita).\n3. **Optimizado para Apple Silicon**: Shaders Metal para GPUs M-series usan memoria unificada eficientemente.\n4. **Sin dependencia de Python**: El servidor de inferencia es C++ puro. Deployar es copiar un binario y un archivo de modelo."},{"heading":"Método 4: SqueezeLLM","level":2,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#mtodo-4-squeezellm","content":"SqueezeLLM es el método que recibe comparativamente poca atención, lo cual es discutiblemente un error. Hace algo fundamentalmente diferente a los otros tres: separa los pese es en un componente cuantizado \"denso\" y una matriz de corrección \"esparsa\":\n\n```\nW ≈ W_cuantizado + S (corrección esparsa)\n```\n\nLa matriz esparsa ` S ` contiene correcciones para los pese es donde el error de cuantización es más alto (los outliers). Estos outliers son típicamente \\<0.5% de todos los pesos, así que ` S ` es extremadamente esparsa y agrega overhead de memoria mínimo.\n\nEl resultado es llamativo: SqueezeLLM a 4-bit logra calidad muy cercana a métodos de 8-bit, con uso de memoria cercano a otros métodos de 4-bit.\n\n| Método | PPL 4-bit (LLaMA-2 7B) | Memoria | Notas |\n| --- | --- | --- | --- |\n| GPTQ | 5.63 | 3.9GB | g128 |\n| AWQ | 5.60 | 3.9GB | g128 |\n| GGUF Q4\\_K\\_M | 5.68 | 4.1GB | Precisión mixta |\n| SqueezeLLM | 5.54 | 4.3GB | Denso + esparso |\n| FP16 | 5.47 | 13.5GB | Baseline |\n\nEl 5.54 de SqueezeLLM está solo 0.07 por encima de FP16, eso es esencialmente sin pérdida para propósitos prácticos. Los 400MB extra de memoria vienen de la matriz de corrección esparsa.\n\n**La contra:** La inferencia de SqueezeLLM requiere kernels CUDA custom para la descomposición esparsa-densa, y el soporte del ecosistema es mínimo. Vas a estar escribiendo tu propio código de serving. Para research o herramientas internas, vale la pena. Para serving de producción a escala, la madurez del ecosistema de GPTQ/AWQ/GGUF gana."},{"heading":"Velocidad de Inferencia Real","level":2,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#velocidad-de-inferencia-real","content":"Los cuatro métodos se corrieron en el mismo hardware con prompts idénticos (512 tokens de input, 256 de output), usando el mejor engine de inferencia disponible para cada método:\n\n**NVIDIA RTX 4090 (24GB VRAM):**\n\n| Método | Engine | 7B tok/s | 13B tok/s | 70B\\* |\n| --- | --- | --- | --- | --- |\n| GPTQ 4-bit | ExLlama v2 | 142 | 88 | 18 |\n| AWQ 4-bit | AutoAWQ | 128 | 79 | 16 |\n| GGUF Q4\\_K\\_M | llama.cpp CUDA | 118 | 72 | 15 |\n| SqueezeLLM 4-bit | CUDA custom | 95 | 54 | , |\n| FP16 | vLLM | 89 | OOM | OOM |\n\n\\*70B requiere offloading a RAM de CPU para todos los métodos de 4-bit en una sola 4090.\n\n**Apple M3 Pro (18GB memoria unificada):**\n\n| Método | Engine | 7B tok/s | 13B tok/s |\n| --- | --- | --- | --- |\n| GGUF Q4\\_K\\_M | llama.cpp Metal | 52 | 34 |\n| GGUF Q4\\_0 | llama.cpp Metal | 58 | 37 |\n| MLX 4-bit | mlx-lm | 47 | 29 |\n\nGGUF domina en Apple Silicon. El backend Metal en llama.cpp está bien optimizado para la arquitectura de memoria de la serie M."},{"heading":"La Matriz de Decisión","level":2,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#la-matriz-de-decisin","content":"Después de una evaluación extensiva, aquí va un framework de decisión práctico:\n\n**Escenario 1: Servidor GPU, inferencia batcheada, máximo throughput** → GPTQ 4-bit con kernels ExLlama v2 vía vLLM o text-generation-inference\n\n**Escenario 2: Inferencia local en tu laptop/desktop** → GGUF Q4\\_K\\_M con llama.cpp (híbrido CPU+GPU si es necesario)\n\n**Escenario 3: Deploy en edge, VRAM limitada, se necesita huella de modelo chica** → AWQ 4-bit (menor overhead de runtime, buen soporte de librerías)\n\n**Escenario 4: Máxima calidad, dispuesto a sacrificar algo de velocidad y conveniencia de ecosistema** → SqueezeLLM 4-bit (más cerca de calidad FP16 en memoria de 4-bit)\n\n**Escenario 5: No se está seguro y solo se desea algo que funcione** → GGUF Q4\\_K\\_M. verdad. Es el más portable, tiene la historia de deployment más simple, funciona en todas las plataformas, y la calidad está a un tiro de piedra de los métodos más complejos."},{"heading":"Hallazgos Notables","level":2,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#hallazgos-notables","content":"**4-bit es mejor que 8-bit naive para muchas tareas.** Un modelo GPTQ 4-bit con calibración apropiada muchas veces supera a un modelo 8-bit simple de round-to-nearest. Los datos de calibración le dan al cuantizador información sobre qué pese es importan, y 4-bit + inteligencia supera a 8-bit + ignorancia.\n\n**Los datos de calibración son el hiperparámetro más subestimado.** Todas las guías dicen \"utilizar 128 muestras de C4.\" Si tu modelo está fine-tuned para generación de código y calibrás con prosa de Wikipedia, se está dejando calidad sobre la mesa. Crear sets de calibración específicos del dominio puede recuperar 0.2-0.4 puntos de perplexity en modelos especializados.\n\n**La cuantización y el KV cache interactúan.** Un modelo Q4 ahorra 70% en memoria de pesos, pero el KV cache sigue siendo FP16 por default. Con 32K de longitud de contexto con un modelo 7B, el KV cache solo son ~2GB. Investigá la cuantización de KV cache a FP8 (vLLM soporta esto) para obtener el beneficio completo.\n\nEl panorama de la cuantización se mueve rápido, para cuando leas esto, capaz haya un método nuevo que cambie el cálculo. Pero los principios no cambian: entendé qué se está intercambiando (precisión, velocidad, compatibilidad), medir con tus datos reales, y los benchmarks independientes sobre datos reales de producción siguen siendo la medida más confiable."},{"heading":"Preguntas frecuentes","level":2,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#questions","content":""},{"heading":"¿Qué método de cuantización debería usar para mi modelo de 7B parámetros?","level":3,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#question-1","content":"Para inferencia GPU con batching: GPTQ 4-bit con kernels ExLlama v2. Para inferencia local de un solo usuario: GGUF Q4\\_K\\_M con llama.cpp. Para deployment en edge con VRAM limitado: AWQ 4-bit. Para máxima calidad con compresión moderada: SqueezeLLM a 4-bit con descomposición densa-y-esparsa."},{"heading":"¿Cuánta calidad pierdo con cuantización de 4-bit?","level":3,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#question-2","content":"En un modelo LLaMA-2 7B, la perplexity FP16 en WikiText-2 es 5.47. GPTQ 4-bit da 5.63 (+0.16), AWQ 4-bit da 5.60 (+0.13), GGUF Q4\\_K\\_M da 5.68 (+0.21), y SqueezeLLM 4-bit da 5.54 (+0.07). Para la mayoría de las aplicaciones, estas diferencias son imperceptibles en la calidad del output."},{"heading":"¿Puedo cuantizar y correr modelos en Apple Silicon?","level":3,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#question-3","content":"Sí. GGUF con llama.cpp tiene el mejor soporte Metal, usa la memoria unificada de la GPU directamente. Para un modelo 13B en Q4\\_K\\_M, eliminars ~35 tok/s en un M3 Pro con 18GB de memoria unificada. MLX también soporta modelos cuantizados nativamente pero con un formato diferente (safetensors cuantizados de MLX)."},{"heading":"Tips","level":2,"url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#article-tips","content":"1. **El set de calibración de AWQ importa enormemente:** No utilizar el ` pile-uncopyrighted ` por defecto para modelos de dominio específico. Crear un set de calibración con datos reales de inferencia, incluso 128 muestras es suficiente. Se ha observado una caída de perplejidad de 0.3 en un modelo de QA médico solo cambiando los datos de calibración a abstracts de PubMed.\n2. **GGUF Q4\\_K\\_M es el punto óptimo para la mayoría de los casos:** Utiliza una mezcla de cuantización de 4-bit y 5-bit, con 5-bit para capas de atención y 4-bit para capas FFN. El flag de ` llama-quantize ` es ` --type q4_K_M `. Típicamente queda dentro de 0.1 de perplejidad de Q5\\_K\\_M con 20% menos de memoria.\n3. **Perfilar la VRAM con ` nvidia-smi dmon -s m ` durante inferencia:** Los modelos cuantizados pueden igualmente provocar OOM si el KV cache crece sin límite. Configurar ` max_seq_len ` explícitamente en la configuración de serving. Un modelo 7B en Q4 usa ~4GB para pesos pero el KV cache a 32K de contexto agrega otros 2GB. Es frecuente olvidar el cache.\n4. **Para inferencia en batch, GPTQ con kernel ` exllama_v2 ` supera a AWQ:** Los kernels CUDA personalizados de ExLlama v2 para dequantización GPTQ son más rápidos que los de AutoAWQ en batch sizes \\>4. Configurar ` disable_exllama=False ` en la configuración de cuantización y verificar que ` torch.cuda.is_bf16_supported() ` devuelva true para mejores resultados.\n\n- llm\n- cuantización\n- gptq\n- awq\n- gguf\n- optimización-inferencia\n\n[Volver al Blog](<https://lucioduran.com/es/blog>)"}],"links":[{"text":"English","url":"https://lucioduran.com/blog/llm-quantization-gptq-awq-gguf-compared"},{"text":"Volver al Blog","url":"https://lucioduran.com/es/blog"}],"structuredData":[{"@context":"https://schema.org","@graph":[{"@type":"BlogPosting","@id":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared#article","mainEntityOfPage":{"@type":"WebPage","@id":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared"},"headline":"Comparación de Cuantización de LLMs: GPTQ, AWQ, GGUF y SqueezeLLM","description":"Una comparación práctica de métodos de cuantización de LLMs con benchmarks reales de perplejidad, uso de memoria y velocidad de inferencia. Cuándo usar cada método, y los casos donde 4-bit supera a 8-bit.","datePublished":"2025-10-11","author":{"@type":"Person","@id":"https://lucioduran.com/#person","name":"Lucio Durán","url":"https://lucioduran.com"},"publisher":{"@type":"Person","@id":"https://lucioduran.com/#person","name":"Lucio Durán","url":"https://lucioduran.com"},"image":"https://statics.lucioduran.com/images/lucioduran-social-card.jpg","url":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared","inLanguage":"es","isPartOf":{"@id":"https://lucioduran.com/blog#blog"},"articleSection":"AI/ML","keywords":"llm, cuantización, gptq, awq, gguf, optimización-inferencia","wordCount":1752,"timeRequired":"PT10M","workTranslation":[{"@type":"BlogPosting","inLanguage":"en","url":"https://lucioduran.com/blog/llm-quantization-gptq-awq-gguf-compared"}]},{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Inicio","item":"https://lucioduran.com/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https://lucioduran.com/es/blog"},{"@type":"ListItem","position":3,"name":"Comparación de Cuantización de LLMs: GPTQ, AWQ, GGUF y SqueezeLLM","item":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared"}]},{"@type":"FAQPage","mainEntity":[{"@type":"Question","name":"¿Qué método de cuantización debería usar para mi modelo de 7B parámetros?","acceptedAnswer":{"@type":"Answer","text":"Para inferencia GPU con batching: GPTQ 4-bit con kernels ExLlama v2. Para inferencia local de un solo usuario: GGUF Q4_K_M con llama.cpp. Para deployment en edge con VRAM limitado: AWQ 4-bit. Para máxima calidad con compresión moderada: SqueezeLLM a 4-bit con descomposición densa-y-esparsa."}},{"@type":"Question","name":"¿Cuánta calidad pierdo con cuantización de 4-bit?","acceptedAnswer":{"@type":"Answer","text":"En un modelo LLaMA-2 7B, la perplexity FP16 en WikiText-2 es 5.47. GPTQ 4-bit da 5.63 (+0.16), AWQ 4-bit da 5.60 (+0.13), GGUF Q4_K_M da 5.68 (+0.21), y SqueezeLLM 4-bit da 5.54 (+0.07). Para la mayoría de las aplicaciones, estas diferencias son imperceptibles en la calidad del output."}},{"@type":"Question","name":"¿Puedo cuantizar y correr modelos en Apple Silicon?","acceptedAnswer":{"@type":"Answer","text":"Sí. GGUF con llama.cpp tiene el mejor soporte Metal, usa la memoria unificada de la GPU directamente. Para un modelo 13B en Q4_K_M, eliminars ~35 tok/s en un M3 Pro con 18GB de memoria unificada. MLX también soporta modelos cuantizados nativamente pero con un formato diferente (safetensors cuantizados de MLX)."}}]}]}],"contentHash":"28d67ad164e0d80d9b69710d39a33d0a98f64ed8da83926c8e7dfdf969650c02","provenance":{"method":"Deterministic serialization of the server-rendered main element","source":"https://lucioduran.com/es/blog/llm-quantization-gptq-awq-gguf-compared","hashAlgorithm":"sha256","hashScope":"JSON document fields before contentHash and provenance","sourceHTMLBytes":74695,"contentBytes":14751}}
