{
  "version": "twinforce.gpu-memory-experiment.v1",
  "author": "Twin Force",
  "date": "2026-10-24",
  "canonical_url": "https://twinforce.es/labs/2026-10-24/memoria-gpu.json",
  "title": "Mediciones propias: memoria de Nemotron 3.5 Bolt E4B en una RTX 4060 Laptop",
  "nature": "Experimento editorial local; no benchmark independiente de calidad del modelo ni evaluación general de todas las GPU.",
  "hardware": {
    "gpu": "NVIDIA GeForce RTX 4060 Laptop GPU",
    "device_memory_total_mib": 8188,
    "driver": "595.91.07",
    "cpu": "13th Gen Intel Core i9-13900H"
  },
  "runtime": {
    "project": "llama.cpp",
    "build": 11854,
    "commit": "8e5a58df8",
    "version": "0.7.0-dev",
    "backend": "CUDA 12.8",
    "precision_kv": "f16",
    "flash_attention": "on",
    "auto_fit": "off",
    "parallel_slots": 1,
    "batch": 512,
    "microbatch": 128,
    "warmup": false
  },
  "model": {
    "name": "NVIDIA-Nemotron-3.5-Bolt-E4B-4GB",
    "file": "Nemotron-3.5-Bolt-E4B-Q4_K_M.gguf",
    "bytes_on_disk": 6180446208,
    "revision": "1db54d5b12533ff1bcaa8e42cf4c667988a1f1be",
    "sha256": "c8af2b8aea10a690a1d9491db744a9446660173cb38fc489612b556615a69612",
    "primary_url": "https://huggingface.co/nvidia/NVIDIA-Nemotron-3.5-Bolt-E4B-4GB"
  },
  "methodology": [
    "Se descargaron el binario oficial y el GGUF oficial; se compararon los SHA-256 con los publicados por GitHub y Hugging Face LFS. No se modificó el sistema ni la venv principal.",
    "Cuatro arranques independientes y secuenciales. Se mantuvieron el mismo modelo, archivo, prompt, semilla, precisión KV, atención, lote y número de slots. Se desactivó el auto-fit. Tres casos cambiaron únicamente el contexto reservado; el cuarto mantuvo 32768 tokens y redujo las capas GPU a 20.",
    "El servidor de cada caso arrancó sin warmup. Se esperó /health=200, se guardaron props y slots, y se realizó una única petición /completion con temperature=0, semilla 20261024 y máximo 32 tokens. Se detuvo sólo ese proceso al acabar.",
    "La petición fija tenía 20 tokens y generó 32. No se llenaron las ventanas de 2048, 8192 o 32768 tokens. El experimento mide reserva y una petición corta, no el pico universal de una conversación que ocupe todo el contexto.",
    "Se muestreó nvidia-smi durante carga e inferencia y se retuvo la memoria residente VmRSS del proceso. Los picos mostrados son los mayores observados por el muestreo; puede haber picos más breves no capturados.",
    "La memoria GPU total de nvidia-smi incluye el escritorio y otros consumidores; no es igual al buffer del modelo ni al coste exclusivo del proceso.",
    "Los buffers de modelo, KV y cómputo se copian de logs de llama.cpp. La tabla de resumen del runtime redondea a MiB enteros; los logs de buffers aportan decimales. No se reconcilian sumando cifras de fuentes o precisiones diferentes.",
    "CPU_Mapped indica regiones mapeadas por el runtime, no que todas sus páginas estén simultáneamente residentes. VmRSS del proceso es una medición distinta y se publica en KiB como informa /proc.",
    "Primera tanda a verbosity 3 conservada como exploración. La tanda principal verbosity 4 añade el desglose de buffers y un caso controlado de offload; los resultados de esta tabla proceden sólo de esa segunda tanda."
  ],
  "why_disk_and_gpu_differ": {
    "observed": "Aun con 43/43 capas declaradas en GPU, los logs conservan buffers CPU_Mapped de 2856.00 y 680.00 MiB. El resumen Host informa 3536 MiB de modelo en los tres casos all. Por tanto, todas las capas trasladables no equivale a todos los tensores en GPU.",
    "source_code_evidence": [
      {
        "url": "https://github.com/ggml-org/llama.cpp/blob/8e5a58df8/src/llama-model.cpp#L1696",
        "fact": "El runtime mantiene la capa de entrada en CPU."
      },
      {
        "url": "https://github.com/ggml-org/llama.cpp/blob/8e5a58df8/src/llama-arch.cpp#L820",
        "fact": "token_embd se clasifica como tensor de la capa de entrada."
      },
      {
        "url": "https://github.com/ggml-org/llama.cpp/blob/8e5a58df8/src/llama-arch.cpp#L1036",
        "fact": "per_layer_token_embd se clasifica como tensor de la capa de entrada."
      },
      {
        "url": "https://github.com/ggml-org/llama.cpp/blob/8e5a58df8/src/models/gemma4.cpp#L50",
        "fact": "Gemma4 puede crear una copia del embedding como tensor de salida cuando no existe una salida separada."
      }
    ],
    "limit": "Los logs publicados no atribuyen por nombre cada uno de los dos buffers CPU a un tensor. No se identifica esa correspondencia ni se presenta la suma CPU + GPU como tamaño del archivo, porque mapeos y copias son conceptos diferentes."
  },
  "prompt": "Explica en una sola frase qué significa reservar memoria para el contexto de un modelo de lenguaje.",
  "cases": [
    {
      "case": "ctx2048-all",
      "context_reserved_tokens": 2048,
      "gpu_layers_requested": "all",
      "gpu_layers_reported": "43/43",
      "gpu_model_buffer_mib": "3023.05",
      "gpu_kv_buffers_mib": [
        "32.00",
        "30.00"
      ],
      "cpu_kv_buffers_mib": [],
      "gpu_compute_buffer_mib": "32.44",
      "runtime_summary_gpu_mib": {
        "self": "3117",
        "model": "3023",
        "context": "62",
        "compute": "32"
      },
      "runtime_summary_host_mib": {
        "self": "3546",
        "model": "3536",
        "context": "0",
        "compute": "10"
      },
      "process_resident_ram_at_ready_kib": "4080412",
      "gpu_device_used_at_ready_mib": 3296,
      "gpu_device_peak_sampled_mib": 3310,
      "gpu_device_baseline_mib": 64,
      "state": "completed",
      "gpu_process_observed": true,
      "prompt_tokens": 20,
      "generated_tokens": 32,
      "command": [
        "llama-server",
        "-m",
        "Nemotron-3.5-Bolt-E4B-Q4_K_M.gguf",
        "-c",
        "2048",
        "-ngl",
        "all",
        "-np",
        "1",
        "--fit",
        "off",
        "-b",
        "512",
        "-ub",
        "128",
        "--no-warmup",
        "--host",
        "127.0.0.1",
        "--port",
        "8894",
        "-ctk",
        "f16",
        "-ctv",
        "f16",
        "--cache-ram",
        "0",
        "-fa",
        "on",
        "-lv",
        "4"
      ]
    },
    {
      "case": "ctx8192-all",
      "context_reserved_tokens": 8192,
      "gpu_layers_requested": "all",
      "gpu_layers_reported": "43/43",
      "gpu_model_buffer_mib": "3023.05",
      "gpu_kv_buffers_mib": [
        "128.00",
        "30.00"
      ],
      "cpu_kv_buffers_mib": [],
      "gpu_compute_buffer_mib": "33.94",
      "runtime_summary_gpu_mib": {
        "self": "3214",
        "model": "3023",
        "context": "158",
        "compute": "33"
      },
      "runtime_summary_host_mib": {
        "self": "3548",
        "model": "3536",
        "context": "0",
        "compute": "12"
      },
      "process_resident_ram_at_ready_kib": "4082244",
      "gpu_device_used_at_ready_mib": 3392,
      "gpu_device_peak_sampled_mib": 3406,
      "gpu_device_baseline_mib": 64,
      "state": "completed",
      "gpu_process_observed": true,
      "prompt_tokens": 20,
      "generated_tokens": 32,
      "command": [
        "llama-server",
        "-m",
        "Nemotron-3.5-Bolt-E4B-Q4_K_M.gguf",
        "-c",
        "8192",
        "-ngl",
        "all",
        "-np",
        "1",
        "--fit",
        "off",
        "-b",
        "512",
        "-ub",
        "128",
        "--no-warmup",
        "--host",
        "127.0.0.1",
        "--port",
        "8894",
        "-ctk",
        "f16",
        "-ctv",
        "f16",
        "--cache-ram",
        "0",
        "-fa",
        "on",
        "-lv",
        "4"
      ]
    },
    {
      "case": "ctx32768-all",
      "context_reserved_tokens": 32768,
      "gpu_layers_requested": "all",
      "gpu_layers_reported": "43/43",
      "gpu_model_buffer_mib": "3023.05",
      "gpu_kv_buffers_mib": [
        "512.00",
        "30.00"
      ],
      "cpu_kv_buffers_mib": [],
      "gpu_compute_buffer_mib": "39.94",
      "runtime_summary_gpu_mib": {
        "self": "3604",
        "model": "3023",
        "context": "542",
        "compute": "39"
      },
      "runtime_summary_host_mib": {
        "self": "3554",
        "model": "3536",
        "context": "0",
        "compute": "18"
      },
      "process_resident_ram_at_ready_kib": "4088392",
      "gpu_device_used_at_ready_mib": 3782,
      "gpu_device_peak_sampled_mib": 3796,
      "gpu_device_baseline_mib": 64,
      "state": "completed",
      "gpu_process_observed": true,
      "prompt_tokens": 20,
      "generated_tokens": 32,
      "command": [
        "llama-server",
        "-m",
        "Nemotron-3.5-Bolt-E4B-Q4_K_M.gguf",
        "-c",
        "32768",
        "-ngl",
        "all",
        "-np",
        "1",
        "--fit",
        "off",
        "-b",
        "512",
        "-ub",
        "128",
        "--no-warmup",
        "--host",
        "127.0.0.1",
        "--port",
        "8894",
        "-ctk",
        "f16",
        "-ctv",
        "f16",
        "--cache-ram",
        "0",
        "-fa",
        "on",
        "-lv",
        "4"
      ]
    },
    {
      "case": "ctx32768-ngl20",
      "context_reserved_tokens": 32768,
      "gpu_layers_requested": "20",
      "gpu_layers_reported": "20/43",
      "gpu_model_buffer_mib": "1725.63",
      "gpu_kv_buffers_mib": [
        "128.00"
      ],
      "cpu_kv_buffers_mib": [
        "384.00",
        "30.00"
      ],
      "gpu_compute_buffer_mib": "150.25",
      "runtime_summary_gpu_mib": {
        "self": "2003",
        "model": "1725",
        "context": "128",
        "compute": "150"
      },
      "runtime_summary_host_mib": {
        "self": "5265",
        "model": "4833",
        "context": "414",
        "compute": "18"
      },
      "process_resident_ram_at_ready_kib": "5836044",
      "gpu_device_used_at_ready_mib": 2182,
      "gpu_device_peak_sampled_mib": 2186,
      "gpu_device_baseline_mib": 64,
      "state": "completed",
      "gpu_process_observed": true,
      "prompt_tokens": 20,
      "generated_tokens": 32,
      "command": [
        "llama-server",
        "-m",
        "Nemotron-3.5-Bolt-E4B-Q4_K_M.gguf",
        "-c",
        "32768",
        "-ngl",
        "20",
        "-np",
        "1",
        "--fit",
        "off",
        "-b",
        "512",
        "-ub",
        "128",
        "--no-warmup",
        "--host",
        "127.0.0.1",
        "--port",
        "8894",
        "-ctk",
        "f16",
        "-ctv",
        "f16",
        "--cache-ram",
        "0",
        "-fa",
        "on",
        "-lv",
        "4"
      ]
    }
  ],
  "editorial_conclusions": [
    "Los cuatro casos completaron una petición usando CUDA y un proceso visible en la GPU.",
    "Con el mismo archivo y43/43capasGPU, el buffer del modelo se mantuvo en 3023.05 MiB, mientras el contexto y el uso observado deGPU cambiaron.",
    "A 32768 tokens, reducir las capas GPU a 20 movió parte del modelo yKV al host: el resumen GPUmodelo pasó a 1725 MiB y el Host del modelo a 4833 MiB. Esto libera GPU a cambio de memoria y trabajo en CPU; no elimina ese coste.",
    "La etiqueta comercial 4GB, el archivo descargado y la memoria reservada en GPU son magnitudes distintas. Una configuración debe verificarse en su hardware, runtime y carga reales; estos resultados no garantizan otras condiciones."
  ]
}
