1 puntos por GN⁺ 4 시간 전 | 1 comentarios | Compartir por WhatsApp
  • En un servidor con doble Xeon E5-2690 v2 de 2013 y DDR3, se ejecutó Gemma 4 26B-A4B Q8_0 solo con CPU, logrando cerca de 5.2 tokens/s en decodificación y alrededor de 16 tokens/s en evaluación de prompts
  • La ruta rápida de ik_llama.cpp presupone AVX2 y FMA3, pero las CPU Ivy Bridge solo soportan AVX1, por lo que hicieron falta cambios de compilación y fallbacks de operaciones para una compilación sin AVX2
  • Mientras el generador de grafos creaba incondicionalmente MOE_FUSED_UP_GATE y FUSED_UP_GATE, el despachador sin AVX2 no tenía una ruta para procesarlas, lo que dejaba unos 240 tensores sin calcular en cada pasada hacia adelante y producía salidas multilingües caóticas
  • Claude encontró el error mediante instrumentación de logits y análisis de código, reemplazó la operación fusionada por dos ggml_mul_mat_id y ggml_fused_mul_unary, mientras que el usuario ejecutó los experimentos y determinó el criterio para un resultado correcto
  • Los servidores empresariales antiguos también pueden servir como alternativa local ante fallas de API de pago o para trabajos batch lentos, pero no se debe usar --run-time-repack, que crea un layout exclusivo para AVX2

Entorno de ejecución de un servidor de almacenamiento de hace 13 años

  • El equipo HP StoreVirtual reutilizado usa doble Xeon E5-2690 v2 de 2013 y memoria DDR3, sin GPU
    • Al ser de la generación Ivy Bridge, solo soporta AVX1 y no soporta AVX2 ni FMA3
    • Originalmente fue fabricado para almacenamiento en disco y costó menos de 300 dólares
  • El modelo ejecutado es Gemma 4 26B-A4B de Google, un modelo de mezcla de expertos (MoE) de pesos abiertos con 26 mil millones de parámetros
  • En el modelo cuantizado Q8_0, la decodificación se midió en cerca de 5.2 tokens/s y la evaluación de prompts en alrededor de 16 tokens/s

El caso de Xeon de 2016 que sirvió como punto de partida

  • A 10 year old Xeon is all you need, compartido en Hacker News, es un caso en el que Gemma 4 se ejecutó sin GPU en un Xeon único de 2016 con 128 GB de DDR3
  • Esa configuración usa ik_llama.cpp y unas 25 flags de ejecución finas
    • Decodificación especulativa
    • Enrutamiento MoE considerando la CPU
    • Flash attention para CPU
    • Reempaquetado de pesos en tiempo de ejecución
  • Se intentó aplicar el mismo enfoque al servidor Ivy Bridge, pero la ejecución se detenía en la fase inicial
    • A diferencia de la CPU Broadwell de 2016, el E5-2690 v2 no tiene AVX2 ni FMA3
    • Ese conjunto de instrucciones está disponible desde Haswell de 2014, es decir, la generación v3 de Intel, y los kernels rápidos estaban escritos asumiéndolo

Diagnóstico y parche con Claude

  • Al recibir la información de la falla inicial, Claude identificó como causa la diferencia en el conjunto de instrucciones de la CPU
  • Continuando un enfoque incompleto que antes se había intentado con un modelo gratuito, modificó rutas críticas de rendimiento en C++ para que hicieran fallback correctamente en CPU anteriores a AVX2
  • El trabajo no terminó con una única solicitud de fix it
    • Leyó código C++ orientado a rendimiento escrito por otro desarrollador
    • Analizó por qué el kernel no era válido en una microarquitectura específica
    • Evitó rutas no soportadas sin descartar las optimizaciones existentes del fork
  • En lugar de escribir directamente los fallbacks de kernels C++, el usuario ejecutó experimentos, leyó las salidas, definió las siguientes preguntas y cumplió el rol de determinar el criterio para un resultado correcto
  • El diagnóstico y el parche fueron realizados por una instancia de Claude ejecutada en ese servidor

Ruta de operaciones rota en la compilación sin AVX2

  • ik_llama.cpp, usado para la inferencia MoE de Gemma 4, es un fork de llama.cpp y por defecto asume AVX2 como requisito mínimo
  • Al desactivar GGML_USE_IQK_MULMAT durante la compilación, se excluye la mayoría de las rutas rápidas y se hace fallback a operaciones escalares/SSE generales
    • Para la multiplicación de matrices Q8_0 habitual, este fallback funciona
    • Sin embargo, en dos operaciones del grafo el fallback no se aplicaba
  • La red feed-forward MoE de Gemma 4 genera las siguientes operaciones
    • MOE_FUSED_UP_GATE: operación que combina la multiplicación de matrices gate·up por experto y SwiGLU
    • FUSED_UP_GATE: versión de operación densa usada en capas no MoE
  • En el despachador de cómputo, ambas operaciones estaban protegidas por la condición GGML_USE_IQK_MULMAT, pero el generador de grafos creaba las operaciones sin condición
    • En el despachador de una compilación sin AVX2 no había ningún case que manejara esos enum
    • Al caer en la rama por defecto, los tensores destino de todas las redes feed-forward de expertos quedaban silenciosamente sin calcular
  • Gemma 4 26B usa 8 expertos activos por token en 30 capas, por lo que en cada pasada hacia adelante terminaba consumiendo unos 240 tensores con valores que habían quedado en buffers de memoria

Pistas reveladas por una salida caótica

  • La salida errónea parecía fluida, pero era una cadena multilingüe sin sentido
    • Los ID de tokens se distribuían de forma uniforme por todo el vocabulario de 262,000 elementos
    • Tailandés, coreano, centinelas <unused>, fragmentos en inglés, etc., se generaban con frecuencias similares
  • Con temperatura 0, la salida era determinista; los resultados con un solo hilo y con múltiples hilos eran idénticos byte por byte y no aparecían NaN
  • Se observaba que una constante grande empujaba el estado oculto en cada capa, aplanando el softmax final
  • Claude instrumentó los logits crudos antes del muestreo para imprimir los 5 tokens principales, el rango, el promedio y el número de NaN
    • El logit promedio del primer token predicho no estaba cerca de 0, sino en +16
    • Cerca del 80% de todo el vocabulario tenía logits positivos
  • Como el sesgo era constante, a diferencia de una corrupción aleatoria, se acotó la causa a que una gran parte del estado oculto estaba usando memoria no inicializada con pequeños valores positivos de punto flotante remanentes

Corrección en tres etapas

  • El parche está compuesto por tres commits encima de main del fork
  • Corrección de compilación sin AVX2

    • Las ramas escalares #else de quantize_row_q8_0_x4 y quantize_row_q8_1_x4_T en iqk_quantize.cpp en realidad referenciaban helpers AVX2 como hsum_i32_8
    • Esas ramas se reescribieron como bucles escalares portables
    • Se agregaron condiciones de protección #if GGML_USE_IQK_MULMAT a algunas llamadas IQK que se habían filtrado a ggml.c y ggml-quants.c
    • Se agregó un include faltante para que iqk_cpu_ops.cpp compilara de forma independiente
    • Sin esta corrección, el fork en sí no compila en hardware sin AVX2
  • Fallback del grafo en tiempo de ejecución

    • En lugar de corregir el despachador, se cambió el generador de grafos para que en esa compilación genere operaciones que ya tienen rutas de cálculo
    • En ggml_moe_up_gate, cuando GGML_USE_IQK_MULMAT está desactivado, se procesan los pesos combinados up_gate_exps
    • La forma del tensor es [n_embd, 2*n_ff, n_experts], donde la primera mitad es gate y la segunda mitad es up
    • Se separa en dos slices con ggml_view_3d
    • Se ejecuta ggml_mul_mat_id en cada slice
    • Se combinan los dos resultados con ggml_fused_mul_unary(gate, up, SILU)
    • Si los pesos gate y up ya están separados, se usan dos ggml_mul_mat_id y una operación fusionada de multiplicación y unaria, sin slicing
    • El mismo fallback se aplicó también a ggml_fused_up_gate, usado en capas no MoE
    • mul_mat_id usa la implementación base de ggml, y fused_mul_unary procesa SILU y la multiplicación de una vez, por lo que todas las operaciones componentes ya tienen una implementación no IQK
    • Todo el cambio está detrás de #if !GGML_USE_IQK_MULMAT, de modo que los resultados de compilaciones con AVX2 son idénticos bit a bit a los existentes
  • Limpieza de stubs de CI

    • Los stubs #else de las fuentes IQK diferían de iqk_mul_mat.h, por lo que ci/run.sh tampoco compilaba en hardware sin AVX2
    • Faltaba el include <cstdint>
    • Algunos stubs tenían firmas distintas, como un parámetro inicial innecesario o la ausencia del parámetro sinks
    • Algunas funciones no tenían stub, lo que provocaba referencias indefinidas en la etapa de enlace
    • Al alinear los stubs con el header, se volvió posible ejecutar la suite de pruebas también en entornos sin AVX2

Costo de rendimiento del fallback y error de reempaquetado

  • El fallback ejecuta dos mul_mat_id en lugar de un solo kernel fusionado, por lo que tiene un costo adicional
  • Esa CPU ya está limitada por el ancho de banda de memoria, y el kernel fusionado original también era exclusivo para AVX2, así que en este entorno no había una ruta de ejecución existente que se estuviera abandonando
  • El rendimiento final en el MoE 26B-A4B es de cerca de 5.2 tokens/s en decodificación y alrededor de 16 tokens/s en evaluación de prompts
  • --run-time-repack reordena al inicio los pesos cuantizados al formato intercalado exclusivo de AVX2 Q8_0_R8
    • En un entorno AVX1, es un bug separado que vuelve a corromper la salida
    • El parche actual no lo corrige y elimina esa flag del script de ejecución

Proceso para acotar la causa

  • La incompatibilidad del conjunto de instrucciones se comprobó fácilmente, pero el problema de que el despachador cayera en la rama por defecto sin error fue difícil de encontrar
  • La revisión de código descartó varios candidatos
    • Los helpers de RMSNorm parecían correctos
    • El fallback AVX1 de ggml_vec_dot_q8_0_q8_0 también parecía correcto
    • Como los resultados de un solo hilo eran idénticos bit a bit, se descartó un error de threading
  • A partir de que el promedio de logits quedaba fijo en +16 y los tokens de cola larga tenían valores similares, se concluyó que una gran parte del flujo residual no estaba inicializada
  • Tras buscar #if GGML_USE_IQK_MULMAT en el despachador, en aproximadamente un minuto se encontraron las dos rutas de operación faltantes

Condiciones de reproducción y alcance de uso

  • Las condiciones de reproducción en equipos previos a AVX2 son las siguientes
    • Hardware: doble Xeon E5-2690 v2, Ivy Bridge, AVX1, DDR3, sin GPU
    • Compilación: compilar ik_llama.cpp de la rama parcheada sin GGML_USE_IQK_MULMAT
    • Modelo: Gemma 4 26B-A4B Q8_0
    • Ejecución: usar las flags habituales de CPU de ik_llama.cpp, pero excluir --run-time-repack
  • Los cambios exactos pueden verse en ikawrakow/ik_llama.cpp PR #2138
    • Al momento de escribir, aún está abierto y esperando revisión de los maintainers, por lo que debe ejecutarse directamente desde la rama
    • Los bugs que aparezcan en el mismo equipo pueden reportarse en el hilo del PR
  • Mantener un modelo local en servidores empresariales antiguos permite usarlo como alternativa cuando se cae una API de pago, o procesar trabajos batch lentos para los que el cobro por token no encaja
  • Se valora más la capacidad de adentrarse directamente en código desconocido y sistemas antiguos que usar servicios de suscripción, y esto se aplica de la misma forma al mantenimiento de una aplicación Rails de hace 15 años o de una base de datos cuyo responsable ya se fue

1 comentarios

 
GN⁺ 4 시간 전
Comentarios de Hacker News
  • Se espera que para mediados de 2027 sea posible ejecutar modelos MoE de más de 200 mil millones de parámetros en hardware de consumo común
    Estoy ejecutando localmente Qwen3.6-35B-A3B en una Mac de 16GB y obtengo entre 7 y 9 tokens por segundo: https://github.com/deepanwadhwa/samosa-chat
    Básicamente, eso significa correr localmente en una MacBook Air con 16GB de RAM un modelo de nivel GPT-4 a esa velocidad

    • Tal vez ni siquiera haga falta esperar tanto. El modelo de pesos ternarios Bonsai 27B que Prism publicó hace unos días ocupa solo unos 7GB y supera los 44 tokens por segundo en una laptop M4 Max: https://huggingface.co/prism-ml/Ternary-Bonsai-27B-mlx-2bit
      Ya está en un rango similar al número de parámetros activos de la mayoría de los modelos de más de 200 mil millones, así que Prism podría sacar uno de ese tipo si quisiera. Eso sí, las redes neuronales recurrentes como HRM no necesitan tantos parámetros, así que se puede debatir si realmente hace falta llegar a esa escala: https://huggingface.co/sapientinc/HRM-Text-1B
    • 7 a 9 tokens por segundo no me parece una velocidad aceptable. No soy experto, pero probando en local sentí que por debajo de 12 a 16 tokens por segundo ya se vuelve frustrante
    • En general coincido con la predicción, pero creo que podría tardar un poco más. Para lograr algo así haría falta una compresión completamente distinta a la actual reducción de bits por parámetro, y en ese escenario la métrica clásica de cantidad de parámetros podría dejar de tener sentido
      Por ejemplo, si en cada capa solo se guarda una semilla de 256 bits y se mete en una función de ruido para generar 16K pesos reales, el almacenamiento por peso podría bajar a menos de 1 bit
    • Estoy corriendo Ornith 35B en Pi y obtengo más de 50 tokens por segundo. Desde que descubrí que Pi también soporta búsqueda y fetch, dejé de necesitar un modelo grande para búsquedas
      Tengo muchas ganas de ver los nuevos modelos que parecen venir este mes y el siguiente, porque podrían cambiar por completo el panorama. Definitivamente vale la pena probar Ornith
    • 9 tokens por segundo me suena difícil de tolerar. Es común gastar un millón de tokens en menos de un día en una sesión de Claude, así que para trabajo real se ve demasiado lento
  • Aunque a algunos no les guste oírlo, creo que el costo por token de los proveedores de inferencia es más barato que la electricidad de correrlo localmente
    Simplificando y contando solo la generación de salida, 5 tokens por segundo son 18,000 tokens por hora, y el costo con un proveedor sería de unos 0.005 dólares. Si asumimos que el servidor consume unos 500W durante la inferencia y tomamos como referencia Alemania, donde la electricidad cuesta 0.3 dólares por kWh, generar esa misma cantidad localmente costaría 0.15 dólares, o sea 30 veces más caro
    Si te preocupa la privacidad, correrlo localmente sigue siendo buena opción, pero hay que tener claro que es mucho menos eficiente que un proveedor de inferencia. A medida que las GPU nuevas mejoren la eficiencia de inferencia, esta brecha también se va a ampliar bastante
    Al principio calculé mal y puse 180 mil tokens, pero en realidad son 18,000 tokens, así que salvo que la electricidad te salga casi gratis, es difícil competir. Además, los proveedores todavía usarán H200/H100 para modelos pequeños, pero cuando se pasen a GB300 o a las GPU Ruby del próximo año, el costo de inferencia podría bajar a una trigésima parte, y el valor principal de los modelos locales probablemente será la privacidad

    • En mi casa, correr Qwen 27B consume unos 400W mientras trabajo, genera cerca de 40 tokens por segundo y procesa prompts —lo más importante— a unos 1,000 tokens por segundo
      En una hora puede procesar 3.6 millones de tokens de entrada o generar 144,000 tokens, y el costo eléctrico es de unos 0.15 dólares. Con Sonnet, procesar esa misma cantidad costaría 7.2 dólares en entrada y 1.4 dólares en generación, así que la nube sale 10 veces más cara para generar y casi 50 veces más cara para procesar
    • En Estados Unidos ni de cerca se paga 0.30 dólares por kWh. En horarios de baja demanda cuesta la mitad, e incluso puedes invertir 1,000 dólares en una batería para guardar electricidad súper barata de 0.11 dólares en esos horarios
      Los proveedores de inferencia están compitiendo por cuota de mercado mientras cargan con deudas enormes, así que claramente los precios van a subir
    • Estaría genial construir un servidor LLM autoalojado independiente alimentado con paneles solares y baterías. Algo como Low Tech Magazine: se desconecta cuando no hay suficiente sol, y se diseña al tamaño necesario para que lo use todos los días una comunidad local, como un grupo de amigos, una calle o un club
      Si democratizamos la IA hasta el punto de que la comunidad la controle directamente, también se podría resolver el problema de los centros de datos, y el nivel de censura y alineación podría decidirse democráticamente dentro de la comunidad. Es una idea parecida a algunas cosas que ha escrito Geohotz
      Los modelos open source pronto serán lo bastante buenos y eficientes como para ofrecer servicio barato con hardware usado. En cada comunidad pequeña, con que haya una persona con conocimientos técnicos y se junten unos cientos de dólares de costo inicial, después se podría operar casi gratis, sin pagar electricidad
      https://solar.lowtechmagazine.com/
    • La eficiencia importa, pero también hay mucha gente con electricidad barata o con equipos eficientes. En un servidor casero AMD Strix Halo se puede servir Gemma4-26B a aproximadamente 70 tokens por segundo usando solo 100W
    • No me importa si cuesta más. La razón para correrlo localmente no es ahorrar dinero, sino ganar libertad y privacidad, y que exista esa alternativa también reduce los costos a largo plazo
      Si no existiera la opción local, los precios de los modelos en la nube serían mucho más altos
  • Es probable que los Xeon duales de esta generación consuman más de 300 W bajo carga. Con la tarifa eléctrica promedio de EE. UU., eso serían 1.35 dólares al día, y más si además hay que enfriar el espacio en verano
    Ignorando el tiempo de procesamiento del prompt, incluso corriéndolo 24 horas al día serían unos 400 mil tokens diarios, así que el costo sería de unos 0.30 dólares por cada millón de tokens de salida. Curiosamente, eso coincide con el precio actual de este modelo en OpenRouter, pero la velocidad de generación en OpenRouter es 8 veces más rápida
    Hay muchas razones para experimentar con LLM locales, como evitar que los datos salgan de tu casa, pero es difícil que convenga económicamente. Habiendo invertido bastante más dinero en equipo de inferencia local en casa, diría que es divertido, pero no una forma de ahorrar

    • Para alguien que vive en una casa real, es un cálculo razonable. Yo vivo en una vivienda rentada y no pago la luz directamente, así que el límite de costo-eficiencia es el momento en que el casero empiece a quejarse
    • Creo que la mayoría no ejecuta modelos localmente para ahorrar dinero, sino para no andar regando su privacidad
    • Se parece a las criptomonedas. Por el costo de la electricidad, para la mayoría sale más barato comprar que minar por cuenta propia
    • En temporadas frías, cuando en casa de todos modos se usa calefacción, también se puede aprovechar el calor residual, así que mejora la rentabilidad
  • Se resumieron resultados de ejecutar varios modelos sin GPU, con Xeon dual y 256 GB de DDR4
    https://gist.github.com/hparadiz/f3596d00a62d8ebb2dadcc46ee5822c7

    • Me pregunto si probó usar solo un CPU para eliminar la penalización de rendimiento por NUMA. Usaría solo la mitad de la memoria, pero me gustaría saber qué tanta diferencia hay en rendimiento
    • Parece que con muchísima RAM lenta, incluso los modelos pequeños corren bastante rápido. Me intriga cómo funcionarían modelos más grandes en este equipo
  • Es bastante lento. Yo estoy obteniendo 8 a 12 tokens por segundo incluso en un CPU de 13 años, aunque puede variar según el tamaño del contexto y otras configuraciones
    https://news.ycombinator.com/item?id=48354801

    • También saco 8 a 9 tokens por segundo con un Xeon E3-1270 V2 a 3.50 GHz y una vieja Nvidia Quadro K2200 de 4 GB. Estoy ejecutando gemma4:e2b y gemma4:12b-it-qat en Ollama
    • ¿No será que el post original usa cuantización Q8 y aquí se está usando Q4?
  • Soy el autor del post original. Parece que mi comentario original fue reportado por alguna razón. Dejé las correcciones en el PR #2138 del proyecto padre: https://github.com/ikawrakow/ik_llama.cpp/pull/2138

  • Este equipo StoreVirtual no parece tener puertos útiles para instalar software. Solo veo algo como puertos USB; me pregunto si la instalación se hace por consola serial

  • Estoy ejecutando Gemma 4 26B en una Mac Pro 2013 con la misma configuración y obtengo alrededor de 5 tokens por segundo. Las tarjetas gráficas duales aquí no sirven de mucho, pero para algunas tareas sigue siendo bastante útil

  • Vi en persona la configuración del sótano y la verdad está impresionante. La próxima vez estaría bueno que también mostraras la impresora 3D

  • Como video medio relacionado, alguien ejecutó un LLM en un Pentium 4 y le puso el apodo NetburstGPT. Claro, es lentísimo
    https://www.youtube.com/watch?v=ILV-eu90te8