Entropic 2.11.1
Local-first agentic inference engine
Loading...
Searching...
No Matches
vram_footprint.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
60#pragma once
61
62#include <cstdint>
63#include <string>
64#include <utility>
65
66namespace entropic {
67
69constexpr uint64_t kBaseKvPerTokenF16 = 16ull * 1024ull;
70
72constexpr int kAllLayersSentinel = 99;
73
75enum class Offload {
76 none,
77 full,
79};
80
83 uint64_t weights_bytes = 0;
84 uint64_t mmproj_bytes = 0;
85 int gpu_layers = -1;
87 std::string cache_type_k = "f16";
88 std::string cache_type_v = "f16";
90};
91
94 bool known = false;
95 uint64_t bytes = 0;
96 const char* reason = "";
97};
98
112inline double kv_scale_for_cache_type(const std::string& type) {
113 static const std::pair<const char*, double> kScales[] = {
114 {"f32", 2.0}, // 4 B/elem
115 {"f16", 1.0}, // 2 B/elem — the baseline
116 {"bf16", 1.0}, // 2 B/elem
117 {"q8_0", 0.53125}, // 34 B / 32 elem = 1.0625 B/elem
118 {"q5_1", 0.375}, // 24 B / 32 elem = 0.75 B/elem
119 {"q5_0", 0.34375}, // 22 B / 32 elem = 0.6875 B/elem
120 {"q4_1", 0.3125}, // 20 B / 32 elem = 0.625 B/elem
121 {"q4_0", 0.28125}, // 18 B / 32 elem = 0.5625 B/elem
122 };
123 double scale = 1.0;
124 for (const auto& entry : kScales) {
125 if (type == entry.first) {
126 scale = entry.second;
127 break;
128 }
129 }
130 return scale;
131}
132
145inline Offload classify_offload(int gpu_layers) {
147 if (gpu_layers < 0 || gpu_layers >= kAllLayersSentinel) {
148 placement = Offload::full;
149 } else if (gpu_layers == 0) {
150 placement = Offload::none;
151 }
152 return placement;
153}
154
166inline double kv_bytes_per_token(const FootprintInputs& in) {
167 const double avg = (kv_scale_for_cache_type(in.cache_type_k)
169 return static_cast<double>(kBaseKvPerTokenF16) * avg;
170}
171
182 const Offload placement = classify_offload(in.gpu_layers);
183 if (placement == Offload::partial_unknown) {
184 est.reason = "partial offload: layer count is not knowable without "
185 "GGUF metadata, so the budget gate stays open";
186 return est;
187 }
188 // The projector follows the weights: offload none and it lives in host RAM.
189 const uint64_t resident = (placement == Offload::full)
191 : 0ull;
192 const int ctx = in.context_length > 0 ? in.context_length : 0;
193 const uint64_t kv = static_cast<uint64_t>(
194 static_cast<double>(ctx) * kv_bytes_per_token(in));
195 est.known = true;
196 est.bytes = resident + kv
197 + static_cast<uint64_t>(in.vram_reserve_mb) * 1024ull * 1024ull;
198 return est;
199}
200
216 uint64_t available_bytes) {
217 FootprintInputs probe = in;
218 probe.context_length = 0;
219 const FootprintEstimate fixed = estimate_vram_footprint(probe);
220 if (!fixed.known || fixed.bytes >= available_bytes) {
221 return 0;
222 }
223 const double per_token = kv_bytes_per_token(in);
224 const uint64_t kv_budget = available_bytes - fixed.bytes;
225 const uint64_t fits = static_cast<uint64_t>(
226 static_cast<double>(kv_budget) / per_token);
227 const uint64_t requested = in.context_length > 0
228 ? static_cast<uint64_t>(in.context_length) : 0ull;
229 uint64_t chosen = fits < requested ? fits : requested;
230 chosen -= chosen % 512ull;
231 return static_cast<int>(chosen);
232}
233
234} // namespace entropic
Activate model on GPU (WARM → ACTIVE).
FootprintEstimate estimate_vram_footprint(const FootprintInputs &in)
Estimate the VRAM a tier will occupy, or report that it cannot.
constexpr uint64_t kBaseKvPerTokenF16
KV bytes per token at f16, the rate the v2.2.4 estimate assumed.
constexpr int kAllLayersSentinel
gpu_layers at or above this means "every layer" (llama.cpp's 99).
@ none
Unconstrained.
double kv_scale_for_cache_type(const std::string &type)
Cost of a KV cache type relative to f16.
Offload classify_offload(int gpu_layers)
Classify a tier's offload request into a priceable placement.
double kv_bytes_per_token(const FootprintInputs &in)
Per-token KV cost in bytes for this tier's cache configuration.
int recommend_context_length(const FootprintInputs &in, uint64_t available_bytes)
Largest context length that fits, for the "won't fit" recommendation.
Offload
Where a tier's weights land, as far as the estimate can tell.
@ none
gpu_layers == 0: weights cost no VRAM.
@ partial_unknown
A layer count we cannot price without GGUF metadata.
@ full
-1 or >= 99: the whole file is resident.
An estimate, or an explicit admission that there isn't one.
bool known
False means "do not gate on this".
uint64_t bytes
Estimated VRAM bytes; 0 when not known.
const char * reason
Why it is unknown, for the log.
Everything the estimate needs, with no orchestrator or filesystem.
int vram_reserve_mb
Configured headroom to leave free.
uint64_t mmproj_bytes
Size of the vision projector, 0 if none.
int context_length
Tier's requested context window.
std::string cache_type_k
KV key cache quantization.
uint64_t weights_bytes
Size of the tier's GGUF on disk.
std::string cache_type_v
KV value cache quantization.
int gpu_layers
Tier's requested offload (-1 = all).