49 Logger::info(
"Processing weights from GGUF data source...");
51 if (
gguf && (
gguf->mapped_tensor_data || !
gguf->tensor_data.empty())) {
53 Logger::info(
"[INIT_WEIGHTS_GGUF] map_gguf_weights(*gguf, *this) CALLED (using function parameter).");
56 Logger::info(
"[INIT_WEIGHTS_GGUF] map_gguf_weights(*gguf_data_, *this) CALLED (using member gguf_data_).");
58 Logger::error(
"[INIT_WEIGHTS_GGUF] map_gguf_weights failed - tensor data not available. No GGUF weights mapped.");
62 Logger::info(
"[INIT_WEIGHTS_GGUF] Using lazy dequantization to prevent OOM");
76 Logger::info(
"[INIT_WEIGHTS_GGUF_DEQUANT] Successfully converted final_norm (BF16) to final_norm_f32. Size: " + std::to_string(this->
final_norm_f32.size()));
82 Logger::info(
"[INIT_WEIGHTS_GGUF] Deferring lm_head dequantization until needed to save memory");
87 this->lm_head_q4k.empty() &&
this->lm_head_q5k.empty() &&
this->lm_head_q8k.empty() &&
88 this->lm_head.empty() && !
this->embed_tokens_f32.empty()) {
90 Logger::info(
"[INIT_WEIGHTS_GGUF] No output.weight: the head is tied to token_embd.weight");
94 Logger::info(
"[INIT_WEIGHTS_GGUF] Deferring all layer weight dequantization until layers are used");
97 for (
int l = 0;
l <
nhl; ++
l) {
100 if (
lw.input_layernorm_f32.empty() && !
lw.input_layernorm.empty()) {
102 if (!
lw.input_layernorm_f32.empty())
Logger::info(
" L" + std::to_string(
l) +
" input_layernorm_f32 populated from BF16. Size: " + std::to_string(
lw.input_layernorm_f32.size()));
104 if (
lw.post_attention_layernorm_f32.empty() && !
lw.post_attention_layernorm.empty()) {
106 if (!
lw.post_attention_layernorm_f32.empty())
Logger::info(
" L" + std::to_string(
l) +
" post_attention_layernorm_f32 populated from BF16. Size: " + std::to_string(
lw.post_attention_layernorm_f32.size()));
111 for (
int l = 0;
l <
nhl; ++
l) {
113 if (
lw.input_layernorm_f32.empty()) {
114 Logger::error(
"[INIT_WEIGHTS_GGUF_CHECK] Layer " + std::to_string(
l) +
115 ": input_layernorm_f32 is EMPTY post-GGUF. This WILL cause GPU init errors if this layer is on GPU.");
117 if (
lw.post_attention_layernorm_f32.empty()) {
118 Logger::error(
"[INIT_WEIGHTS_GGUF_CHECK] Layer " + std::to_string(
l) +
119 ": post_attention_layernorm_f32 is EMPTY post-GGUF. This WILL cause GPU init errors if this layer is on GPU.");
122 Logger::info(
"[INIT_WEIGHTS_GGUF] Finished per-layer NORM F32 vector checks post-GGUF.");
125 Logger::fatal(
"TinyLlamaModel::initialize_weights called with neither GGUF nor SafeTensors loader. Cannot initialize weights.");
126 throw std::runtime_error(
"Model weights source (GGUF or SafeTensors) not provided to initialize_weights.");
129 Logger::info(
"Finished initializing model weights logic block.");
132 Logger::error(
"[INIT_WEIGHTS_FINAL_CHECK] final_norm_f32 is EMPTY. This WILL cause errors if final normalization is needed in F32.");
138 Logger::error(
"[INIT_WEIGHTS_FINAL_CHECK] embed_tokens_f32 is EMPTY. This WILL cause errors if token embeddings are needed in F32.");
147 Logger::info(
"Constructing TinyLlamaModel from SafeTensorsLoader (is_gguf_file_loaded set to false).");
150 Logger::info(
"TinyLlamaModel construction from SafeTensorsLoader complete.");
157 ,
cublas_handle_(
nullptr),
token_embedding_table_dev_(
nullptr),
lm_head_dev_(
nullptr),
final_norm_dev(
nullptr),
w_q_dev_(
nullptr),
w_k_dev_(
nullptr),
w_v_dev_(
nullptr),
w_o_dev_(
nullptr),
w_gate_dev_(
nullptr),
w_up_dev_(
nullptr),
w_down_dev_(
nullptr),
all_freqs_cis_dev(
nullptr),
x_dev_(
nullptr),
x_norm_dev_(
nullptr),
x_resid1_dev_(
nullptr),
x_resid2_dev_(
nullptr),
q_dev_(
nullptr),
k_dev_(
nullptr),
v_dev_(
nullptr),
attn_out_dev_(
nullptr),
attn_proj_dev_(
nullptr),
gate_vec_dev_(
nullptr),
up_vec_dev_(
nullptr),
swiglu_vec_dev_(
nullptr),
mlp_down_dev_(
nullptr),
logits_dev_(
nullptr),
token_embedding_table_f32_dev_(
nullptr),
lm_head_f32_dev_(
nullptr),
w_q_f32_dev_(
nullptr),
w_k_f32_dev_(
nullptr),
w_v_f32_dev_(
nullptr),
w_o_f32_dev_(
nullptr),
w_gate_f32_dev_(
nullptr),
w_up_f32_dev_(
nullptr),
w_down_f32_dev_(
nullptr)
164 if (this->
model_path_.empty() && !model_path.empty()) {
167 std::unique_ptr<SafeTensorsLoader>
loader =
nullptr;
169 this->model_path_.substr(
this->model_path_.size() - 5) ==
".gguf") {
174 " for gguf_meta/weight loading based on CLI mmap preference: " +
186 const char*
only = std::getenv(
"EMBER_IR_ONLY");
188 const auto j = nlohmann::json::parse(
ir);
191 if (!
tuned &&
j.value(
"family_hint",
"") ==
"llama")
192 Logger::info(
"[IR] family_hint llama, but not the tuned llama path's graph (" +
why +
193 "): the interpreter runs it");
196 const auto&
m =
j.at(
"model");
202 if (
const char*
c = std::getenv(
"EMBER_IR_CTX"))
203 if (std::atoi(
c) > 0)
209 for (
const auto&
s :
j.at(
"block").value(
"state", nlohmann::json::array()))
210 if (
s.value(
"kind",
"") ==
"kv") {
217 for (
const auto&
s :
j.at(
"block").value(
"state", nlohmann::json::array()))
218 if (
s.value(
"kind",
"") ==
"recurrent" &&
s.value(
"op",
"") ==
"linear_attention" &&
219 !
s.value(
"tensors", nlohmann::json::array()).empty())
220 heads =
s.at(
"tensors").at(0).at(
"shape").at(0).get<
int>();
225 Logger::info(
"GGUF served by the paperkiln IR interpreter only (family_hint '" +
226 j.value(
"family_hint",
"") +
"'): llama weights are not loaded.");
233 if (cli_gpu_layer_request < 0) {
235 Logger::info(
"TinyLlamaModel GGUF Ctor CALC: CLI hint < 0 (all GPU). num_cpu_offload_layers set to 0.");
236 }
else if (cli_gpu_layer_request == 0) {
243 Logger::info(
"TinyLlamaModel GGUF Ctor CALC: CLI GPU layer request ("+ std::to_string(
cli_gpu_layer_request) +
") >= total layers. num_cpu_offload_layers set to 0.");
250 Logger::warning(
"TinyLlamaModel GGUF Ctor CALC: num_hidden_layers from GGUF is <= 0. Defaulting num_cpu_offload_layers to 0. CLI GPU req: " + std::to_string(
cli_gpu_layer_request));
255 ", this->config_.num_hidden_layers = " + std::to_string(
this->config_.num_hidden_layers));
256 }
catch (
const std::exception&
e) {
257 Logger::error(
"Failed to load or parse GGUF file: " + std::string(
e.what()));
268 Logger::info(
"Successfully loaded and parsed config.json for SafeTensors model.");
271 Logger::warning(
"Failed to load config.json or it was not found for SafeTensors model. Proceeding with initial_config defaults and CLI overrides.");
276 if (cli_gpu_layer_request < 0) {
278 }
else if (cli_gpu_layer_request == 0) {
289 Logger::warning(
"SafeTensors path: num_hidden_layers is 0 from JSON/default. Defaulting num_cpu_offload_layers to 0 despite CLI GPU request: " + std::to_string(
cli_gpu_layer_request));
295 loader = std::make_unique<SafeTensorsLoader>(
model_path);
297 }
catch (
const std::exception&
e) {
298 Logger::error(
"Failed to initialize SafeTensorsLoader: " + std::string(
e.what()));
302 throw std::runtime_error(
303 "Unsupported model file type. Please use .gguf or .safetensors");
307 ", config_.num_hidden_layers = " + std::to_string(
this->config_.num_hidden_layers));
312 Logger::warning(
"Clamping num_cpu_offload_layers: was < 0, set to 0.");
316 ") exceeds total hidden layers (" + std::to_string(
this->config_.num_hidden_layers) +
317 "). Clamping to " + std::to_string(
this->config_.num_hidden_layers) +
" (all CPU).");
322 ", this->config_.num_hidden_layers = " + std::to_string(
this->config_.num_hidden_layers));
323 Logger::info(
"Final ModelConfig (before initialize_weights/rope):");
336 if (this->
gguf_data_->tensor_infos_map.empty()) {
337 Logger::error(
"[CTOR_GGUF_PRE_INIT_W] CRITICAL: gguf_data_->tensor_infos_map is EMPTY. Weights will not be loaded by map_gguf_weights.");
340 Logger::error(
"[CTOR_GGUF_PRE_INIT_W] CRITICAL: config_.is_gguf_file_loaded is TRUE, but gguf_data_ pointer IS NULL. Weights cannot be loaded.");
342 Logger::info(
"[CTOR_GGUF_PRE_INIT_W] Not a GGUF file load context (e.g., SafeTensors). Skipping gguf_data_ check here.");
349 Logger::info(
"TinyLlamaModel: IR-only GGUF, weights left to the interpreter.");
355 Logger::info(
"TinyLlamaModel (from path string) constructed and initialized successfully.");
361 model_path_(
"loaded_from_gguf_data_memory")
364 ,
cublas_handle_(
nullptr),
token_embedding_table_dev_(
nullptr),
lm_head_dev_(
nullptr),
final_norm_dev(
nullptr),
w_q_dev_(
nullptr),
w_k_dev_(
nullptr),
w_v_dev_(
nullptr),
w_o_dev_(
nullptr),
w_gate_dev_(
nullptr),
w_up_dev_(
nullptr),
w_down_dev_(
nullptr),
all_freqs_cis_dev(
nullptr),
x_dev_(
nullptr),
x_norm_dev_(
nullptr),
x_resid1_dev_(
nullptr),
x_resid2_dev_(
nullptr),
q_dev_(
nullptr),
k_dev_(
nullptr),
v_dev_(
nullptr),
attn_out_dev_(
nullptr),
attn_proj_dev_(
nullptr),
gate_vec_dev_(
nullptr),
up_vec_dev_(
nullptr),
swiglu_vec_dev_(
nullptr),
mlp_down_dev_(
nullptr),
logits_dev_(
nullptr),
token_embedding_table_f32_dev_(
nullptr),
lm_head_f32_dev_(
nullptr),
w_q_f32_dev_(
nullptr),
w_k_f32_dev_(
nullptr),
w_v_f32_dev_(
nullptr),
w_o_f32_dev_(
nullptr),
w_gate_f32_dev_(
nullptr),
w_up_f32_dev_(
nullptr),
w_down_f32_dev_(
nullptr)
367 Logger::info(
"TinyLlamaModel constructor entered (with pre-loaded GGUFData). Model path placeholder: " +
model_path_);
375 ") exceeds total hidden layers (" + std::to_string(
this->config_.num_hidden_layers) +
376 "). Clamping to " + std::to_string(
this->config_.num_hidden_layers) +
" layers on CPU (all CPU).");
383 Logger::info(
"TinyLlamaModel (with pre-loaded GGUFData) constructed and initialized successfully.");
390 if (active_num_gpu_layers > 0) {
391 Logger::info(
"Freeing TinyLlamaModel CUDA resources...");
395 Logger::error(
"cuBLAS handle destruction failed with error code: " +
406 Logger::error(
"cuBLAS handle destruction failed with error code: " +
420 if (
layer.input_layernorm_dev) {
422 layer.input_layernorm_dev =
nullptr;
424 if (
layer.post_attention_layernorm_dev) {
426 layer.post_attention_layernorm_dev =
nullptr;
588 Logger::info(
"Freed persistent GPU workspace buffers.");
589 Logger::info(
"Finished freeing TinyLlamaModel CUDA weight memory.");
591 Logger::info(
"CPU-only mode: No GPU resources to free.");
596 std::vector<float>& input,
615 Logger::info(
"[CPU_FWD_MEM] Starting layer " + std::to_string(
l) +
" processing");
619 Logger::info(
"[CPU_FWD] ------ START Layer " + std::to_string(
l) +
620 " (pos=" + std::to_string(
n_tokens) +
") ------");
627 lw.input_layernorm_f32.empty()
629 :
lw.input_layernorm_f32;
631 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": Allocating QKV vectors");
634 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": About to ensure_q_proj_dequantized");
636 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": ensure_q_proj_dequantized completed");
643 else throw std::runtime_error(
"Layer " + std::to_string(
l) +
": No Q proj weights (f32, q8k, q8, q4k, q6k, bf16) for CPU");
646 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": About to ensure_k_proj_dequantized");
648 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": ensure_k_proj_dequantized completed");
655 else throw std::runtime_error(
"Layer " + std::to_string(
l) +
": No K proj weights (f32, q8k, q8, q4k, q6k, bf16) for CPU");
657 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": About to ensure_v_proj_dequantized");
659 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": ensure_v_proj_dequantized completed");
666 else throw std::runtime_error(
"Layer " + std::to_string(
l) +
": No V proj weights (f32, q8k, q8, q4k, q6k, bf16) for CPU");
671 if (
static_cast<size_t>(
l) <
kv_cache->layers.size()) {
675 Logger::error(
"KV Cache access out of bounds in CPU forward. Layer " + std::to_string(
l) +
676 ", n_tokens: " + std::to_string(
n_tokens) +
677 ", configured layer_max_seq_len: " + std::to_string(
layer_max_seq_len) +
". Skipping KV update.");
679 Logger::error(
"KV Cache layer_max_seq_len is 0, but n_tokens > 0. Layer " + std::to_string(
l) +
". Skipping KV update.");
687 Logger::error(
"KV Cache layer index " + std::to_string(
l) +
" out of bounds for kv_cache->layers.size() = " + std::to_string(
kv_cache->layers.size()));
709 for (
int d = 0; d <
head_dim; ++d) {
716 for (
int d = 0; d <
head_dim; ++d) {
726 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": About to ensure_o_proj_dequantized");
728 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": ensure_o_proj_dequantized completed");
735 else throw std::runtime_error(
"Layer " + std::to_string(
l) +
": No O proj weights (f32, q8k, q8, q4k, q6k, bf16) for CPU");
743 lw.post_attention_layernorm_f32.empty()
745 :
lw.post_attention_layernorm_f32;
752 lw.moe_router_f32.data(),
lw.moe_gate_exps_f32.data(),
lw.moe_up_exps_f32.data(),
757 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": About to ensure_gate_proj_dequantized");
759 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": ensure_gate_proj_dequantized completed");
766 else throw std::runtime_error(
"Layer " + std::to_string(
l) +
": No Gate proj weights (f32, q8k, q8, q4k, q6k, bf16) for CPU");
769 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": About to ensure_up_proj_dequantized");
771 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": ensure_up_proj_dequantized completed");
778 else throw std::runtime_error(
"Layer " + std::to_string(
l) +
": No Up proj weights (f32, q8k, q8, q4k, q6k, bf16) for CPU");
789 if (!
lw.gate_proj_f32.empty() || !
lw.gate_proj_q8_0.empty() || !
lw.gate_proj_q4k.empty() ||
790 !
lw.gate_proj_q6k.empty() || !
lw.gate_proj_q8k.empty() || !
lw.gate_proj.empty()) {
805 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": About to ensure_down_proj_dequantized");
807 Logger::info(
"[CPU_FWD_MEM] Layer " + std::to_string(
l) +
": ensure_down_proj_dequantized completed");
814 else throw std::runtime_error(
"Layer " + std::to_string(
l) +
": No Down proj weights (f32, q8k, q8, q4k, q6k, bf16) for CPU");
822 if (std::getenv(
"TINYLLAMA_LAYER_TRACE") !=
nullptr) {
823 auto l2 = [](
const std::vector<float>&
v) {
825 for (
float x :
v)
s +=
double(
x) *
x;
828 fprintf(
stderr,
"[ENG_SUBOP] L%d pos=%d ln1=%g Vraw=%g attnout=%g attn=%g res1=%g ln2=%g ffn=%g out=%g\n",
834 Logger::info(
"[CPU_FWD] ------ END Layer " + std::to_string(
l) +
835 " (pos=" + std::to_string(
n_tokens) +
") ------");
847 Logger::info(
"[CPU_FWD] All layers processed on CPU. Performing final RMSNorm and Logits.");
863 else throw std::runtime_error(
"No valid LM Head weights (f32, q8k, q8, q4k, q6k, bf16) found for CPU final stage.");
876std::vector<float> TinyLlamaModel::forward_device(
886 Logger::fatal(
"Number of attention heads is zero during forward_device.");
887 throw std::runtime_error(
"Division by zero: n_heads is zero.");
895 Logger::warning(
"forward_device called with no GPU layers to process (num_gpu_layers = " + std::to_string(
num_gpu_layers) +
"). Returning empty.");
899 Logger::error(
"forward_device called with null x_input_dev. This should be model_->x_dev_.");
911 static const bool decode_timing = std::getenv(
"EMBER_DECODE_TIMING") !=
nullptr;
912 auto t_mark = std::chrono::steady_clock::now();
916 const auto now = std::chrono::steady_clock::now();
928 const char*
v = std::getenv(
"EMBER_DECODE_OPT");
948 throw std::runtime_error(
"[TM::fw_dev pos=" + std::to_string(
pos) +
" L" + std::to_string(
l_model_idx) +
"] Error: input_layernorm_dev is nullptr. GPU layer cannot proceed.");
957 phase(
"layer.norm1");
960 phase(
"layer.ensure_weights");
1029 Logger::error(
"KVCache layer index " + std::to_string(
l_model_idx) +
" out of bounds for kv_cache->layers access in forward_device.");
1033 phase(
"layer.rope_kv");
1099 phase(
"layer.attention");
1122 phase(
"layer.o_proj_resid_norm2");
1161 phase(
"final_norm");
1165 const char*
v = std::getenv(
"EMBER_DECODE_LMHEAD");
1166 return v && std::string(
v) ==
"bf16";
1178 Logger::error(
"LM head (lm_head_dev_ for BF16) is null. Cannot calculate logits on GPU.");
1187 phase(
"logits_d2h");
1199std::vector<float> TinyLlamaModel::forward_device_graph(
int token_id,
int pos,
KVCache*
kv_cache) {
1200 static const bool enabled = [] {
1201 const char*
v = std::getenv(
"EMBER_DECODE_GRAPH");
1202 const char*
o = std::getenv(
"EMBER_DECODE_OPT");
1203 return !(
v && std::string(
v) ==
"0") && !(
o && std::string(
o) ==
"0");
1240 std::vector<float>
table(
static_cast<size_t>(
vs) *
hs);
1241 for (
int t = 0;
t <
vs; ++
t) {
1243 if (
static_cast<int>(
e.size()) !=
hs) {
1247 std::copy(
e.begin(),
e.end(),
table.begin() +
static_cast<size_t>(
t) *
hs);
1253 const void* key =
kv_cache->layers[0].k_dev_fp32;
1265 Logger::warning(
"[decode graph] stream capture unavailable; using per-launch decode.");
1271 for (
int l = 0;
l <
L; ++
l) {
1309 "); using per-launch decode.");
1313 Logger::info(
"[decode graph] captured the decode step (" + std::to_string(
L) +
" layers).");
1334 Logger::error(
"[CPU_LOGITS_BATCH] final_batch_activations size mismatch. Expected: " +
1350 Logger::error(
"[CPU_LOGITS_BATCH] Final RMSNorm weights are empty (neither f32 nor bf16 available).");
1363 Logger::info(
"[CPU_LOGITS_BATCH] Using F32 LM Head weights.");
1367 Logger::info(
"[CPU_LOGITS_BATCH] Using Q8_0 LM Head weights.");
1371 Logger::info(
"[CPU_LOGITS_BATCH] Using Q6_K LM Head weights.");
1375 Logger::info(
"[CPU_LOGITS_BATCH] Using Q4_K LM Head weights.");
1378 }
else if (!
lm_head.empty()) {
1379 Logger::info(
"[CPU_LOGITS_BATCH] Using BF16 LM Head weights (converting to F32 for matmul).");
1382 Logger::error(
"[CPU_LOGITS_BATCH] Failed to convert BF16 LM Head to F32.");
1388 Logger::error(
"[CPU_LOGITS_BATCH] No valid LM Head weights found (F32, Q8_0, Q6_K, Q4_K, BF16).");
1403 std::string
pos_str =
"token_positions=[";
1408 std::string
seq_str =
"original_sequence_indices=[";
1415 Logger::error(
"[CPU_BATCH_GENERATION] batch_input_activations size mismatch. Expected: " +
1422 Logger::error(
"[CPU_BATCH_GENERATION] token_positions size mismatch. Expected: " +
1432 Logger::error(
"[CPU_BATCH_GENERATION] Error: num_attention_heads is zero.");
1450 lw.input_layernorm_f32.empty()
1452 :
lw.input_layernorm_f32;
1463 if (!
lw.q_proj_f32.empty()) {
1465 }
else if (!
lw.q_proj_q8_0.empty()) {
1467 }
else if (!
lw.q_proj_q6k.empty()) {
1469 }
else if (!
lw.q_proj_q4k.empty()) {
1472 Logger::error(
"[CPU_BATCH_GENERATION] Layer " + std::to_string(
l) +
": No Q proj weights found for CPU (batched)");
1477 if (!
lw.k_proj_f32.empty()) {
1479 }
else if (!
lw.k_proj_q8_0.empty()) {
1481 }
else if (!
lw.k_proj_q6k.empty()) {
1483 }
else if (!
lw.k_proj_q4k.empty()) {
1486 Logger::error(
"[CPU_BATCH_GENERATION] Layer " + std::to_string(
l) +
": No K proj weights found for CPU (batched)");
1491 if (!
lw.v_proj_f32.empty()) {
1493 }
else if (!
lw.v_proj_q8_0.empty()) {
1495 }
else if (!
lw.v_proj_q6k.empty()) {
1497 }
else if (!
lw.v_proj_q4k.empty()) {
1500 Logger::error(
"[CPU_BATCH_GENERATION] Layer " + std::to_string(
l) +
": No V proj weights found for CPU (batched)");
1516 #pragma omp parallel if(num_tokens_in_batch > 1)
1550 #pragma omp critical
1587#if defined(__AVX2__) || defined(__SSE2__) || defined(__ARM_NEON)
1591 for (
int d = 0; d <
head_dim; ++d) {
1611#if defined(__AVX2__) || defined(__SSE2__) || defined(__ARM_NEON)
1614 for (
int d = 0; d <
head_dim; ++d) {
1627 if(!
lw.o_proj_f32.empty()) {
1629 }
else if (!
lw.o_proj_q8_0.empty()) {
1631 }
else if (!
lw.o_proj_q6k.empty()) {
1633 }
else if (!
lw.o_proj_q4k.empty()) {
1636 Logger::error(
"[CPU_BATCH_GENERATION] Layer " + std::to_string(
l) +
": No O proj weights found for CPU");
1650 lw.post_attention_layernorm_f32.empty()
1652 :
lw.post_attention_layernorm_f32;
1659 if (!
lw.gate_proj_f32.empty()) {
1661 }
else if (!
lw.gate_proj_q8_0.empty()) {
1663 }
else if (!
lw.gate_proj_q6k.empty()) {
1665 }
else if (!
lw.gate_proj_q4k.empty()) {
1668 Logger::error(
"[CPU_BATCH_GENERATION] Layer " + std::to_string(
l) +
": No gate_proj weights found for CPU");
1672 if (!
lw.up_proj_f32.empty()) {
1674 }
else if (!
lw.up_proj_q8_0.empty()) {
1676 }
else if (!
lw.up_proj_q6k.empty()) {
1678 }
else if (!
lw.up_proj_q4k.empty()) {
1681 Logger::error(
"[CPU_BATCH_GENERATION] Layer " + std::to_string(
l) +
": No up_proj weights found for CPU");
1695 if (!
lw.down_proj_f32.empty()) {
1697 }
else if (!
lw.down_proj_q8_0.empty()) {
1699 }
else if (!
lw.down_proj_q6k.empty()) {
1701 }
else if (!
lw.down_proj_q4k.empty()) {
1704 Logger::error(
"[CPU_BATCH_GENERATION] Layer " + std::to_string(
l) +
": No down_proj weights found for CPU");
1717 if (
kv_cache->current_batch_size > 0) {
1735 ", old_batch_seq_len=" + std::to_string(
kv_cache->batch_seq_lens[
seq_idx]) +
1769 static const bool on = std::getenv(
"EMBER_PREFILL_DEBUG") !=
nullptr;
1792 for (
auto& op :
ops_) {
1799 Op op{
name,
nullptr,
nullptr};
1809 std::map<std::string, double>
collect() {
1810 std::map<std::string, double>
out;
1814 for (
size_t i = 0;
i <
ops_.size(); ++
i) {
1827 out[
"gpu_busy_in_ops"] =
busy;
1828 out[
"gpu_idle_between_ops"] =
idle;
1840 std::vector<Op>
ops_;
1844std::vector<float> TinyLlamaModel::forward_device_batch_prefill(
1862 Logger::debug(
"[FWD_DEV_BATCH_PREFILL_PARAMS] hidden_size: " + std::to_string(hidden_size) +
1863 ", head_dim: " + std::to_string(
head_dim) +
1865 ", n_kv_dim: " + std::to_string(
n_kv_dim) +
1866 ", vocab_size: " + std::to_string(vocab_size) +
1911 const float alpha = 1.0f;
1912 const float beta = 0.0f;
1916 Logger::fatal(
"cublasSetStream failed in forward_device_batch_prefill");
1917 throw std::runtime_error(
"cublasSetStream failed");
2191 std::vector<float>
h_logits(vocab_size);
2214 ") would be out of bounds (" + std::to_string(
kv_cache->max_seq_len_config_) +
"). Skipping.");
2230 " cannot log K/V cache: null pointers, log_elems_kv <= 0, or local_n_kv_dim_for_log <=0.");
2234 " out of bounds for kv_cache->layers (size " + std::to_string(
kv_cache->layers.size()) +
")");
2239 Logger::info(
"[FWD_DEV_BATCH_PREFILL_EXIT] Function finished.");
2242std::vector<std::vector<float>> TinyLlamaModel::forward_device_batch_generation(
2250 throw std::runtime_error(
"forward_device_batch_generation: mixture-of-experts models are not supported");
2255 Logger::error(
"[FWD_DEV_BATCH_GENERATION] token_positions size mismatch. Expected: " +
2260 Logger::error(
"[CPU_BATCH_GENERATION] original_sequence_indices size mismatch. Expected: " +
2311 Logger::fatal(
"cublasSetStream failed in forward_device_batch_generation");
2312 throw std::runtime_error(
"cublasSetStream failed");
2322 Logger::info(
"[FWD_DEV_BATCH_GENERATION_LAYER_START] Processing Layer: model_idx=" + std::to_string(
l_model_idx) +
", gpu_idx=" + std::to_string(
l_gpu_idx) +
2486 vocab_size *
sizeof(
float),
2493 Logger::info(
"[FWD_DEV_BATCH_GENERATION_EXIT] Function finished.");
2606 ", falling back to FP32");
2620 }
catch (
const std::exception&
e) {
2632 ": " +
e.what() +
". Falling back to FP32 and disabling batched BF16 GEMMs for this session.");
2642 " or Tensor Cores unavailable)");
2650 static const bool tf32 = [] {
2651 const char*
v = std::getenv(
"EMBER_GEMM_TF32");
2652 return v ==
nullptr || std::string(
v) !=
"0";
2665float* TinyLlamaModel::moe_scratch(
int T) {
2691std::vector<float> TinyLlamaModel::forward_device_verify(
const std::vector<int>& tokens,
int pos,
KVCache*
kv_cache) {
2692 const int n =
static_cast<int>(tokens.size());
2723 std::vector<float>
emb((
size_t)
n *
hs);
2724 for (
int i = 0;
i <
n; ++
i) {
2726 if (
e.size() !=
static_cast<size_t>(
hs))
return {};
2727 std::copy(
e.begin(),
e.end(),
emb.begin() + (
size_t)
i *
hs);
2730 for (
int l = 0;
l <
L; ++
l) {
2740 for (
int i = 0;
i <
n; ++
i)
2759 std::vector<float>
out((
size_t)
n *
vs);
static void log_vector_stats(const std::string &name, const std::vector< float > &v, int n_show=5)
static void debug(const std::string &message)
static void warning(const std::string &message)
static std::string ptrToString(const void *ptr)
static void info(const std::string &message)
static void error(const std::string &message)
static void fatal(const std::string &message)
Main class for loading tensors from SafeTensors format files (single or sharded)
static bool load_model_config_from_json(const std::string &model_path_or_dir, ModelConfig &config_to_populate)
Loads model configuration from a JSON file corresponding to a .safetensors model path.
bool use_bf16_tensor_cores_
~TinyLlamaModel()
Destructor. Cleans up all allocated resources.
std::vector< float > lookup_embedding(int token_id)
Lookup the embedding vector for a given token ID.
void ensure_up_proj_dequantized(int layer_idx)
std::vector< float > final_norm_f32
std::vector< uint16_t > final_norm
void ensure_v_proj_dequantized(int layer_idx)
std::vector< block_q4_K > lm_head_q4k
std::vector< float > forward_cpu_logits_batch(const std::vector< float > &final_batch_activations, int num_tokens_in_batch)
friend void map_gguf_weights(const GGUFData &gguf, TinyLlamaModel &model)
std::vector< block_q6_K > lm_head_q6k
std::vector< std::pair< float, float > > precomputed_freqs_cis_
bool bf16_batch_gemm_failed_
void initialize_gpu_and_rope()
TinyLlamaModel(const ModelConfig &config, const SafeTensorsLoader &loader)
Construct a TinyLlamaModel from a SafeTensorsLoader.
void ensure_embed_tokens_dequantized()
std::vector< LayerWeights > layers
void ensure_o_proj_dequantized(int layer_idx)
void clear_layer_dequantized_weights(int layer_idx)
void ensure_k_proj_dequantized(int layer_idx)
std::unique_ptr< class CPUBatchProcessor > cpu_batch_processor_
std::vector< block_q8_0 > lm_head_q8_0
std::vector< uint16_t > lm_head
void ensure_f32_concatenated_weights_loaded()
std::vector< std::vector< float > > forward_cpu_batch_generation(const std::vector< float > &batch_input_activations, const std::vector< int > &token_positions, const std::vector< int > &original_sequence_indices, int num_tokens_in_batch, KVCache *kv_cache)
void ensure_bf16_concatenated_weights_loaded()
void ensure_q_proj_dequantized(int layer_idx)
void initialize_weights(const SafeTensorsLoader *loader, const GGUFData *gguf)
std::vector< float > forward_cpu_batch(const std::vector< float > &batch_input_activations, int num_tokens_in_batch, int num_cpu_layers_to_process, int start_pos_in_sequence, KVCache *kv_cache, const std::vector< int > &prompt_lengths={})
void ensure_down_proj_dequantized(int layer_idx)
void ensure_gate_proj_dequantized(int layer_idx)
std::vector< float > embed_tokens_f32
std::vector< float > forward(std::vector< float > &input, int n_tokens, KVCache *kv_cache, const std::vector< int > *attention_mask)
Run the forward pass for the model on CPU layers.
void ensure_lm_head_dequantized()
std::unique_ptr< GGUFData > gguf_data_
std::vector< float > lm_head_f32
std::vector< block_q8_K > lm_head_q8k
void gemm_rm_f32_cuda(cublasHandle_t handle, const float *X, const float *W, float *Y, int T, int O, int I, cudaStream_t stream)
void moe_ffn_cuda(cublasHandle_t handle, const float *x, int T, int d, int d_ff, int E, int k, bool renorm, const float *router, const float *gate_exps, const float *up_exps, const float *down_exps, float *scratch, float *out, cudaStream_t stream)
void decode_embed_cuda(const float *table_dev, float *out_dev, const int *step_dev, int hidden_size, int vocab_size, cudaStream_t stream)
void add_residual_batch_cuda(float *d_output_batch, const float *d_input_a_batch, const float *d_input_b_batch, int num_tokens, int hidden_size, cudaStream_t stream)
void matvec_f32_f32_cuda(cublasHandle_t handle, const float *mat_f32_dev, const float *vec_f32_dev, float *out_f32_dev, int rows, int cols, cudaStream_t stream)
Implementation of matrix-vector multiplication with FP32.
size_t moe_ffn_scratch_floats(int T, int d, int d_ff, int E, int k)
void kv_write_devpos_cuda(float *k_cache_dev, float *v_cache_dev, const float *k_dev, const float *v_dev, const int *step_dev, int row, cudaStream_t stream)
void rope_cuda(float *x_dev, int num_heads, int head_dim, const float *all_freqs_cis_dev_base, int pos, bool use_adjacent_pairing, cudaStream_t stream)
void attention_cuda_selective_dequant(const float *Q_current_dev, const int8_t *K_quantized_cache_base, const int8_t *V_quantized_cache_base, const float *K_scales_cache_base, const float *V_scales_cache_base, float *selective_k_dequant_buffer, float *selective_v_dequant_buffer, float *out_dev, int num_heads, int current_seq_len, int head_dim, float scale, int cache_max_seq_len, int cache_num_kv_heads, cudaStream_t stream)
void rope_batch_cuda(float *d_q_batch, float *d_k_batch, const float *d_all_freqs_cis_base, int num_tokens, int num_q_heads, int num_kv_heads, int head_dim, int start_pos_in_kv_cache, bool use_adjacent_pairing, cudaStream_t stream)
void add_residual_cuda(const float *matvec_out_dev, const float *residual_dev, float *result_dev, int n, cudaStream_t stream)
void matvec_bf16_f32_cuda(cublasHandle_t handle, const uint16_t *mat_bf16_dev, const float *vec_f32_dev, float *out_f32_dev, int rows, int cols, bool use_tensor_cores, cudaStream_t stream)
Matrix-vector multiplication with BF16 matrix and FP32 vector/output on GPU.
void swiglu_cuda(const float *gate_dev, const float *up_dev, float *out_dev, int n, cudaStream_t stream)
void rmsnorm_vector_cuda_optimized(const float *x_dev, const float *weight_dev, float *out_dev, int n, float eps, cudaStream_t stream)
Optimized wrappers using the new high-performance kernels.
void attention_devpos_cuda(const float *Q_current_dev, const float *K_layer_cache_base, const float *V_layer_cache_base, float *out_dev, int num_heads, int head_dim, float scale, int cache_max_seq_len, int cache_num_kv_heads, const int *step_dev, cudaStream_t stream)
void gemm_f32_to_bf16_f32_cuda(cublasHandle_t handle, bool transa_user, bool transb_user, int m_user, int n_user, int k_user, const float *alpha_user, const float *A_f32_user, int lda_user, const uint16_t *B_bf16_user, int ldb_user, const float *beta_user, float *C_f32_user, int ldc_user, cudaStream_t stream)
void rope_devpos_cuda(float *x_dev, int num_heads, int head_dim, const float *all_freqs_cis_dev_base, const int *step_dev, bool use_adjacent_pairing, cudaStream_t stream)
void swiglu_batch_cuda(float *d_out_batch, const float *d_gate_act_batch, const float *d_up_act_batch, int num_tokens, int intermediate_size, cudaStream_t stream)
void attention_cuda(const float *Q_current_dev, const float *K_layer_cache_base, const float *V_layer_cache_base, float *out_dev, int num_heads, int current_seq_len, int head_dim, float scale, int cache_max_seq_len, int cache_num_kv_heads, cudaStream_t stream)
void update_kv_cache_cuda(float *cache_base_ptr, const float *current_kv_head_vector, int pos, int kv_head_idx, int max_seq_len, int num_kv_heads, int head_dim, cudaStream_t stream)
void attention_decode_at_cuda(const float *Q_current_dev, const float *K_layer_cache_base, const float *V_layer_cache_base, float *out_dev, int num_heads, int seq_len, int head_dim, float scale, int cache_max_seq_len, int cache_num_kv_heads, cudaStream_t stream)
void rmsnorm_vector_cuda(const float *x_dev, const float *weight_dev, float *out_dev, int n, float eps, cudaStream_t stream)
Implementation of RMS normalization with device pointers.
void attention_cuda_optimized(const float *Q_current_dev, const float *K_layer_cache_base, const float *V_layer_cache_base, float *out_dev, int num_heads, int current_seq_len, int head_dim, float scale, int cache_max_seq_len, int cache_num_kv_heads, cudaStream_t stream)
GGUFData load_gguf_meta(const std::string &filename, bool use_mmap)
Loads GGUF metadata and optionally memory-maps tensor data.
Parser for GGUF (GPT-Generated Unified Format) files.
const float * p[kIrDepthSourcesMax]
Logging utilities for the TinyLlama implementation.
ModelConfig parse_model_config_from_gguf(const GGUFData &gguf)
void log_vector_summary(const std::string &name, const std::vector< float > &v, int head_count=5)
Constants used throughout the TinyLlama model implementation.
bool tuned_llama_match(const std::string &ir_json, const GGUFData &gguf, std::string *why)
std::string find_ir(const GGUFData &gguf)
int token_id(const std::vector< std::string > &tokens, const std::string &text)
Weight quantization structures and functions for model compression.
SafeTensors format loader for efficient tensor loading, supporting single and sharded models.
Complete representation of a GGUF file's contents.
Key-Value cache for a single transformer layer.
Complete Key-Value cache for all transformer layers.
Model configuration structure holding architecture and hyperparameters.
int num_cpu_offload_layers
bool enable_memory_efficient_layers
bool use_kvcache_quantization
bool use_optimized_cuda_kernels
int max_position_embeddings
void apply_rope_vector(std::vector< float > &x, int num_heads, int head_dim, int current_token_pos, const std::vector< std::pair< float, float > > &all_freqs_cis, int max_pos_embeddings, bool use_adjacent_pairing)
void matvec_q8k_f32_vector_cpu(const std::vector< block_q8_K > &mat_q8k, const std::vector< float > &vec_f32, std::vector< float > &out_f32, int rows, int cols, bool log_first_block)
void matvec_q6k_f32_vector_cpu(const std::vector< block_q6_K > &mat_q6k, const std::vector< float > &vec_f32, std::vector< float > &out_f32, int rows, int cols, bool log_first_block)
void matvec_bf16_f32_vector_cpu(const std::vector< uint16_t > &mat_bf16, const std::vector< float > &vec_f32, std::vector< float > &out_f32, int rows, int cols)
void matvec_f32_f32_vector_cpu(const std::vector< float > &mat_f32, const std::vector< float > &vec_f32, std::vector< float > &out_f32, int rows, int cols)
void simd_scaled_add(float *dst, const float *src, float scale, int n)
void matmul_q4k_f32_batch_cpu(const std::vector< block_q4_K > &mat_q4k, const std::vector< float > &batch_input_activations, std::vector< float > &batch_output_activations, int num_tokens, int output_dim, int input_dim)
std::vector< float > bf16vec_to_float_vec(const std::vector< uint16_t > &v_bf16)
void softmax_vector_cpu(const std::vector< float > &x, std::vector< float > &out)
float simd_dot_product(const float *a, const float *b, int n)
void matvec_q4k_f32_vector_cpu(const std::vector< block_q4_K > &mat_q4k, const std::vector< float > &vec_f32, std::vector< float > &out_f32, int rows, int cols, bool log_first_block)
void matmul_q8_0_f32_batch_cpu(const std::vector< block_q8_0 > &mat_q8_0, const std::vector< float > &batch_input_activations, std::vector< float > &batch_output_activations, int num_tokens, int output_dim, int input_dim)
void matmul_f32_f32_batch_cpu(const std::vector< float > &mat_weights, const std::vector< float > &batch_input_activations, std::vector< float > &batch_output_activations, int num_tokens, int output_dim, int input_dim)
void gelu_new_cpu(const std::vector< float > &x, std::vector< float > &out)
void silu_cpu(const std::vector< float > &x, std::vector< float > &out)
void matmul_q6k_f32_batch_cpu(const std::vector< block_q6_K > &mat_q6k, const std::vector< float > &batch_input_activations, std::vector< float > &batch_output_activations, int num_tokens, int output_dim, int input_dim)
void moe_ffn_f32_cpu(const float *x, int d, int d_ff, int E, int k, const float *router, const float *gate_exps, const float *up_exps, const float *down_exps, float *out, bool renorm)
void rmsnorm_batch_cpu(const std::vector< float > &x_batch, const std::vector< float > &weight, std::vector< float > &out_batch, int num_tokens, int hidden_size, float eps)
void rmsnorm_vector_cpu(const std::vector< float > &x, const std::vector< float > &weight, std::vector< float > &out, float eps)
void matvec_q8_0_f32_vector_cpu(const std::vector< block_q8_0 > &mat_q8_0, const std::vector< float > &vec_f32, std::vector< float > &out_f32, int rows, int cols, bool log_first_block)