32 ") exceeds total hidden layers (" + std::to_string(
nhl) +
33 "). Clamping to " + std::to_string(
nhl) +
" layers on CPU.");
41 if (
hs <= 0)
throw std::runtime_error(
"Invalid model config: hidden_size must be positive.");
42 if (
vs <= 0)
throw std::runtime_error(
"Invalid model config: vocab_size must be positive.");
43 if (
n_heads <= 0)
throw std::runtime_error(
"Invalid model config: num_attention_heads must be positive.");
44 if (
n_kv_heads <= 0)
throw std::runtime_error(
"Invalid model config: num_key_value_heads must be positive.");
45 if (
hs %
n_heads != 0)
throw std::runtime_error(
"Invalid model config: hidden_size not divisible by num_attention_heads.");
50 Logger::info(
"Precomputing RoPE frequencies on CPU (always done).");
61 Logger::info(
"Finished precomputing RoPE cos/sin frequencies on CPU.");
64#define SAFE_CUDA_FREE(ptr) if(ptr) { cudaFree(ptr); ptr = nullptr; }
67 Logger::info(
"No layers assigned to GPU (active_num_gpu_layers = 0). Cleaning up existing CUDA resources and skipping GPU initialization.");
70 for (
int i = 0;
i <
nhl; ++
i) {
97 throw std::runtime_error(
"Failed to initialize cuBLAS: " + std::to_string(
cublas_status));
101 Logger::info(
"EMBER_DETERMINISTIC: deterministic CUDA mode on (fixed-order decode reductions; cuBLAS "
102 "workspace " + std::string(std::getenv(
"CUBLAS_WORKSPACE_CONFIG") ? std::getenv(
"CUBLAS_WORKSPACE_CONFIG") :
"default") +
103 ", atomics not allowed).");
119 if (std::getenv(
"EMBER_DISABLE_BF16") !=
nullptr) {
120 Logger::info(
"EMBER_DISABLE_BF16 set: BF16 Tensor Core path disabled, all GEMMs FP32.");
123 Logger::info(
"GPU " + std::string(
props.name) +
" (CC " + std::to_string(
props.major) +
"." + std::to_string(
props.minor) +
") supports BF16 Tensor Cores AND model dimensions (hs: " + std::to_string(
config_.
hidden_size) +
", vs: " + std::to_string(
config_.
vocab_size) +
") are compatible. Enabling Tensor Core path for matvec_bf16_f32.");
126 Logger::info(
"GPU " + std::string(
props.name) +
" (CC " + std::to_string(
props.major) +
"." + std::to_string(
props.minor) +
") supports BF16 Tensor Cores, BUT model dimensions (hs: " + std::to_string(
config_.
hidden_size) +
" (must be div by 8), vs: " + std::to_string(
config_.
vocab_size) +
" (must be div by 4)) are NOT compatible. Disabling Tensor Core path for matvec_bf16_f32.");
129 Logger::info(
"GPU " + std::string(
props.name) +
" (CC " + std::to_string(
props.major) +
"." + std::to_string(
props.minor) +
") does not meet criteria for BF16 Tensor Core use (requires CC >= 7.5). Disabling Tensor Core path for matvec_bf16_f32.");
134 Logger::info(
"Converting final_norm (BF16) to FP32 for GPU.");
141 Logger::info(
"Copied final_norm weights (FP32) to GPU.");
143 Logger::warning(
"Final norm weights (FP32) are empty, skipping GPU copy. This might be an issue if GPU layers are expected to use it.");
147 if (
static_cast<size_t>(
i) <
layers.size()) {
155 Logger::info(
"[INIT_DEBUG_PRE_LOOP] layers[0].input_layernorm_f32.empty(): " + std::string(
layers[0].input_layernorm_f32.empty() ?
"YES" :
"NO") +
156 ", Size: " + std::to_string(
layers[0].input_layernorm_f32.size()));
159 if (
static_cast<size_t>(
i) >=
layers.size()) {
160 Logger::error(
"Layer index " + std::to_string(
i) +
" out of bounds for layers vector (size: " + std::to_string(
layers.size()) +
")");
166 if (
layers[
i].input_layernorm_f32.empty() && !
layers[
i].input_layernorm.empty()) {
169 if (
layers[
i].post_attention_layernorm_f32.empty() && !
layers[
i].post_attention_layernorm.empty()) {
173 if (!
layers[
i].input_layernorm_f32.empty()) {
178 ", Size used for malloc: " + std::to_string(
layers[
i].input_layernorm_f32.size() *
sizeof(
float)) +
" bytes (" +
179 std::to_string(
layers[
i].input_layernorm_f32.size()) +
" elements). Host vector empty: " + (
layers[
i].input_layernorm_f32.empty() ?
"YES" :
"NO"));
182 throw std::runtime_error(
"GPU Layer " + std::to_string(
i) +
": input_layernorm_f32 weights are empty. Cannot offload to GPU without them.");
185 if (!
layers[
i].post_attention_layernorm_f32.empty()) {
189 throw std::runtime_error(
"GPU Layer " + std::to_string(
i) +
": post_attention_layernorm_f32 weights are empty. Cannot offload to GPU without them.");
192 Logger::info(
"Finished processing layer norm weights for GPU layers.");
204 Logger::info(
"Copied token_embedding_table (bf16 direct from model.embed_tokens) to GPU.");
209 #pragma omp parallel for
215 Logger::info(
"Converted token_embedding_table (fp32 source -> bf16) to GPU.");
220 #pragma omp parallel for
225 #pragma omp parallel for
231 Logger::info(
"Dequantized token_embedding_table (Q8_0 -> fp32 -> bf16) to GPU.");
236 #pragma omp parallel for
241 #pragma omp parallel for
247 Logger::info(
"Dequantized token_embedding_table (Q4_K -> fp32 -> bf16) to GPU.");
252 #pragma omp parallel for
257 #pragma omp parallel for
263 Logger::info(
"Dequantized token_embedding_table (Q6_K -> fp32 -> bf16) to GPU.");
269 ". Flag token_embeddings_processed_to_gpu_bf16: YES");
272 Logger::warning(
"Token embeddings were not processed to GPU as BF16, despite GPU layers being active. This might indicate missing source embedding data in the model structure or an unhandled GGUF type for embeddings.");
275 Logger::info(
"No GPU layers active, skipping token embedding table processing for GPU.");
287 Logger::info(
"Copied lm_head (bf16 direct from model.lm_head) to GPU.");
292 #pragma omp parallel for
298 Logger::info(
"Converted lm_head (fp32 source -> bf16) to GPU.");
303 #pragma omp parallel for
308 #pragma omp parallel for
314 Logger::info(
"Dequantized lm_head (Q8_0 -> fp32 -> bf16) to GPU.");
319 #pragma omp parallel for
324 #pragma omp parallel for
330 Logger::info(
"Dequantized lm_head (Q4_K -> fp32 -> bf16) to GPU.");
335 #pragma omp parallel for
340 #pragma omp parallel for
346 Logger::info(
"Dequantized lm_head (Q6_K -> fp32 -> bf16) to GPU.");
351 Logger::warning(
"LM head was not processed to GPU as BF16, despite GPU layers being active. This might indicate missing source LM head data in the model structure or an unhandled GGUF type for LM head.");
354 Logger::info(
"No GPU layers active, skipping LM head processing for GPU.");
365 Logger::error(
"[INIT_GPU_ROPE] Host lm_head_f32 is EMPTY. Cannot populate lm_head_f32_dev_. This WILL CAUSE a cublasSgemm error in the final matvec. Check model loading and initialize_weights logic for lm_head_f32 population.");
373 Logger::info(
"Finished processing embedding and LM head tables for GPU.");
383 Logger::info(
"Copied all precomputed RoPE frequencies to persistent GPU buffer.");
385 Logger::warning(
"Host precomputed_freqs_cis_ is empty. Skipping GPU RoPE buffer allocation. This WILL cause issues if GPU layers use RoPE.");
387 Logger::info(
"Finished processing RoPE frequencies for GPU.");
389 Logger::info(
"No GPU layers active, skipping RoPE GPU buffer allocation.");
400#define REALLOC_GPU_WORKSPACE(ptr, sz) SAFE_CUDA_FREE(ptr); gpuErrchk(cudaMalloc(&ptr, sz));
415 Logger::info(
"Finished allocating/reallocating GPU workspace buffers.");
417 Logger::info(
"No GPU layers active, skipping GPU workspace buffer allocation.");
432 Logger::info(
"Allocated SELECTIVE KVCache dequantization buffers (K and V) on GPU. Size per buffer: " +
436 Logger::warning(
"Selective KVCache dequantization buffer size is 0. Skipping allocation.");
461 Logger::info(
"Concatenating BF16 weights for GPU layers on host (zero-padding if missing for a layer)...");
466 if (!
lw.q_proj.empty()) {
467 h_q.insert(
h_q.end(),
lw.q_proj.begin(),
lw.q_proj.end());
472 if (!
lw.k_proj.empty()) {
473 h_k.insert(
h_k.end(),
lw.k_proj.begin(),
lw.k_proj.end());
478 if (!
lw.v_proj.empty()) {
479 h_v.insert(
h_v.end(),
lw.v_proj.begin(),
lw.v_proj.end());
484 if (!
lw.o_proj.empty()) {
485 h_o.insert(
h_o.end(),
lw.o_proj.begin(),
lw.o_proj.end());
490 if (!
lw.gate_proj.empty()) {
496 if (!
lw.up_proj.empty()) {
497 h_up.insert(
h_up.end(),
lw.up_proj.begin(),
lw.up_proj.end());
502 if (!
lw.down_proj.empty()) {
509#define ALLOC_COPY_CONCAT_BF16(dev_ptr, host_vec, weight_name_str) \
510 SAFE_CUDA_FREE(dev_ptr); \
511 if (!host_vec.empty()) { \
512 gpuErrchk(cudaMalloc(&dev_ptr, host_vec.size() * sizeof(uint16_t))); \
513 gpuErrchk(cudaMemcpy(dev_ptr, host_vec.data(), host_vec.size() * sizeof(uint16_t), cudaMemcpyHostToDevice)); \
514 Logger::info("Copied concatenated " weight_name_str " (BF16) to GPU for GPU layers."); \
515 } else if (active_num_gpu_layers > 0) { \
516 Logger::info("Host vector for concatenated " weight_name_str " (BF16) is empty. Skipping GPU copy."); \
522#undef ALLOC_COPY_CONCAT_BF16
525 Logger::info(
"Skipping BF16 concatenated layer weight processing (first GPU layer appears not to use BF16 q_proj, or no GPU layers).");
530 Logger::info(
"DEFERRING concatenated F32 weight processing for GPU layers to save memory during initialization");
531 Logger::info(
"Concatenated F32 weights will be processed on-demand during first inference");
540 Logger::info(
"Finished deferring concatenated F32 weight processing for GPU layers.");
552 Logger::info(
"CUDA not available or no GPU layers configured. Model will run entirely on CPU.");
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)
bool use_bf16_tensor_cores_
std::vector< block_q6_K > embed_tokens_q6k
std::vector< float > final_norm_f32
std::vector< uint16_t > final_norm
std::vector< block_q4_K > lm_head_q4k
std::vector< block_q6_K > lm_head_q6k
std::vector< std::pair< float, float > > precomputed_freqs_cis_
void initialize_gpu_and_rope()
void ensure_embed_tokens_dequantized()
std::vector< LayerWeights > layers
std::vector< block_q8_0 > embed_tokens_q8_0
std::vector< block_q4_K > embed_tokens_q4k
std::vector< block_q8_0 > lm_head_q8_0
std::vector< uint16_t > lm_head
std::vector< uint16_t > embed_tokens
std::vector< float > embed_tokens_f32
void ensure_lm_head_dequantized()
std::vector< float > lm_head_f32
constexpr size_t GGML_QK8_0
constexpr size_t GGML_QK_K
Block size constants for different quantization formats.
const float * p[kIrDepthSourcesMax]
Logging utilities for the TinyLlama implementation.
Constants used throughout the TinyLlama model implementation.
void deterministic_cublas_env()
void dequantize_q4_k_m(const block_q4_K *qblock, float *output, int num_weights_in_block, bool log_this_block)
void dequantize_q8_0_block(const block_q8_0 *qblock, float *output)
Dequantizes a Q8_0 block to float32.
void dequantize_q6_k(const block_q6_K *qblock, float *output, int num_weights_in_block, bool log_this_block)
Weight quantization structures and functions for model compression.
int num_cpu_offload_layers
int max_position_embeddings
std::vector< float > bf16vec_to_float_vec(const std::vector< uint16_t > &v_bf16)
uint16_t float32_to_bfloat16(float val)