41 if (
lw.moe_router_f32.empty() && !
lw.moe_router_q8_0.empty()) {
44 lw.moe_router_q8_0.clear();
45 lw.moe_router_q8_0.shrink_to_fit();
59 auto drop = [](
const std::vector<float>& f32,
auto&...
quant) {
60 if (f32.empty())
return;
66 drop(
lw.q_proj_f32,
lw.q_proj_q4k,
lw.q_proj_q5k,
lw.q_proj_q6k,
lw.q_proj_q8_0,
lw.q_proj_q8k);
67 drop(
lw.k_proj_f32,
lw.k_proj_q4k,
lw.k_proj_q5k,
lw.k_proj_q6k,
lw.k_proj_q8_0,
lw.k_proj_q8k);
68 drop(
lw.v_proj_f32,
lw.v_proj_q4k,
lw.v_proj_q5k,
lw.v_proj_q6k,
lw.v_proj_q8_0,
lw.v_proj_q8k);
69 drop(
lw.o_proj_f32,
lw.o_proj_q4k,
lw.o_proj_q5k,
lw.o_proj_q6k,
lw.o_proj_q8_0,
lw.o_proj_q8k);
70 drop(
lw.gate_proj_f32,
lw.gate_proj_q4k,
lw.gate_proj_q5k,
lw.gate_proj_q6k,
lw.gate_proj_q8_0,
lw.gate_proj_q8k);
71 drop(
lw.up_proj_f32,
lw.up_proj_q4k,
lw.up_proj_q5k,
lw.up_proj_q6k,
lw.up_proj_q8_0,
lw.up_proj_q8k);
72 drop(
lw.down_proj_f32,
lw.down_proj_q4k,
lw.down_proj_q5k,
lw.down_proj_q6k,
lw.down_proj_q8_0,
lw.down_proj_q8k);
91 }
else if (!this->
lm_head.empty()) {
99 if (!
lw.q_proj_f32.empty())
return;
112 Logger::info(
"[DEQUANT_MEM] Layer " + std::to_string(
layer_idx) +
": Q-proj dequantization completed, f32 size=" + std::to_string(
lw.q_proj_f32.size()));
133#define EMBER_RECOVERABLE(w) \
134 (!layer.w##_q4k.empty() || !layer.w##_q5k.empty() || !layer.w##_q6k.empty() || !layer.w##_q8k.empty() || \
135 !layer.w##_q8_0.empty() || !layer.w.empty())
144#undef EMBER_RECOVERABLE
153 if (!
lw.k_proj_f32.empty())
return;
169 if (!
lw.v_proj_f32.empty())
return;
185 if (!
lw.o_proj_f32.empty())
return;
201 if (!
lw.gate_proj_f32.empty())
return;
218 if (!
lw.up_proj_f32.empty())
return;
235 if (!
lw.down_proj_f32.empty())
return;
258 Logger::info(
"Loading concatenated F32 weights for optimal GPU performance");
260 Logger::info(
"Loading F32 concatenated weights on-demand for GPU inference");
299 }
else if (!
q8_vec.empty()) {
301 for (
size_t i = 0;
i <
q8_vec.size(); ++
i) {
318 throw std::runtime_error(
"Layer " + std::to_string(
l_model_idx) +
": No " +
weight_name +
" weights found for GPU processing");
334 return lw.q_proj_f32;
336 [](
const LayerWeights&
lw) ->
const std::vector<uint16_t>& {
return lw.q_proj; },
337 [](
const LayerWeights&
lw) ->
const std::vector<block_q8_0>& {
return lw.q_proj_q8_0; },
338 [](
const LayerWeights&
lw) ->
const std::vector<block_q4_K>& {
return lw.q_proj_q4k; },
339 [](
const LayerWeights&
lw) ->
const std::vector<block_q6_K>& {
return lw.q_proj_q6k; },
350 Logger::info(
"Cleared Q-proj CPU memory immediately after GPU upload");
357 return lw.k_proj_f32;
359 [](
const LayerWeights&
lw) ->
const std::vector<uint16_t>& {
return lw.k_proj; },
360 [](
const LayerWeights&
lw) ->
const std::vector<block_q8_0>& {
return lw.k_proj_q8_0; },
361 [](
const LayerWeights&
lw) ->
const std::vector<block_q4_K>& {
return lw.k_proj_q4k; },
362 [](
const LayerWeights&
lw) ->
const std::vector<block_q6_K>& {
return lw.k_proj_q6k; },
372 Logger::info(
"Cleared K-proj CPU memory immediately after GPU upload");
379 return lw.v_proj_f32;
381 [](
const LayerWeights&
lw) ->
const std::vector<uint16_t>& {
return lw.v_proj; },
382 [](
const LayerWeights&
lw) ->
const std::vector<block_q8_0>& {
return lw.v_proj_q8_0; },
383 [](
const LayerWeights&
lw) ->
const std::vector<block_q4_K>& {
return lw.v_proj_q4k; },
384 [](
const LayerWeights&
lw) ->
const std::vector<block_q6_K>& {
return lw.v_proj_q6k; },
401 return lw.o_proj_f32;
403 [](
const LayerWeights&
lw) ->
const std::vector<uint16_t>& {
return lw.o_proj; },
404 [](
const LayerWeights&
lw) ->
const std::vector<block_q8_0>& {
return lw.o_proj_q8_0; },
405 [](
const LayerWeights&
lw) ->
const std::vector<block_q4_K>& {
return lw.o_proj_q4k; },
406 [](
const LayerWeights&
lw) ->
const std::vector<block_q6_K>& {
return lw.o_proj_q6k; },
424 return lw.gate_proj_f32;
426 [](
const LayerWeights&
lw) ->
const std::vector<uint16_t>& {
return lw.gate_proj; },
427 [](
const LayerWeights&
lw) ->
const std::vector<block_q8_0>& {
return lw.gate_proj_q8_0; },
428 [](
const LayerWeights&
lw) ->
const std::vector<block_q4_K>& {
return lw.gate_proj_q4k; },
429 [](
const LayerWeights&
lw) ->
const std::vector<block_q6_K>& {
return lw.gate_proj_q6k; },
446 return lw.up_proj_f32;
448 [](
const LayerWeights&
lw) ->
const std::vector<uint16_t>& {
return lw.up_proj; },
449 [](
const LayerWeights&
lw) ->
const std::vector<block_q8_0>& {
return lw.up_proj_q8_0; },
450 [](
const LayerWeights&
lw) ->
const std::vector<block_q4_K>& {
return lw.up_proj_q4k; },
451 [](
const LayerWeights&
lw) ->
const std::vector<block_q6_K>& {
return lw.up_proj_q6k; },
468 return lw.down_proj_f32;
470 [](
const LayerWeights&
lw) ->
const std::vector<uint16_t>& {
return lw.down_proj; },
471 [](
const LayerWeights&
lw) ->
const std::vector<block_q8_0>& {
return lw.down_proj_q8_0; },
472 [](
const LayerWeights&
lw) ->
const std::vector<block_q4_K>& {
return lw.down_proj_q4k; },
473 [](
const LayerWeights&
lw) ->
const std::vector<block_q6_K>& {
return lw.down_proj_q6k; },
490 std::vector<float>
cat;
493 if (
lw.moe_router_f32.empty() && !
lw.moe_router_q8_0.empty())
495 const std::vector<float>&
v =
get(
lw);
498 " weights for the GPU");
499 cat.insert(
cat.end(),
v.begin(),
v.end());
514 Logger::info(
"Successfully loaded all concatenated F32 weights for GPU layers");
519 Logger::info(
"Loading concatenated BF16 weights for Tensor Core acceleration");
526 Logger::info(
"Converting F32 weights to BF16 for Tensor Core acceleration");
571 Logger::info(
"Successfully loaded all concatenated BF16 weights for Tensor Core acceleration");
587 Logger::info(
"Successfully freed all BF16 concatenated weights");
602 if (
lw.q_proj_f32_dev &&
lw.k_proj_f32_dev &&
lw.v_proj_f32_dev &&
603 lw.o_proj_f32_dev &&
lw.gate_proj_f32_dev &&
lw.up_proj_f32_dev &&
lw.down_proj_f32_dev) {
623 Logger::info(
"JIT loading layer " + std::to_string(
layer_idx) +
" weights to GPU (with aggressive eviction)");
641 ". Attempting emergency cleanup...");
653 throw std::runtime_error(
"GPU OOM: Cannot allocate " + std::to_string(
f32_weights.size() *
sizeof(
float)) +
655 " even after emergency cleanup. Try reducing --n-gpu-layers.");
673 [&
lw]() ->
const std::vector<float>& {
return lw.q_proj_f32; },
681 [&
lw]() ->
const std::vector<float>& {
return lw.k_proj_f32; },
689 [&
lw]() ->
const std::vector<float>& {
return lw.v_proj_f32; },
697 [&
lw]() ->
const std::vector<float>& {
return lw.o_proj_f32; },
705 [&
lw]() ->
const std::vector<float>& {
return lw.gate_proj_f32; },
706 lw.gate_proj_f32_dev,
713 [&
lw]() ->
const std::vector<float>& {
return lw.up_proj_f32; },
721 [&
lw]() ->
const std::vector<float>& {
return lw.down_proj_f32; },
722 lw.down_proj_f32_dev,
727 Logger::info(
"CPU-only build: ensure_layer_weights_on_gpu is a no-op for layer " + std::to_string(
layer_idx));
737 if (
lw.q_proj_f32_dev) {
cudaFree(
lw.q_proj_f32_dev);
lw.q_proj_f32_dev =
nullptr; }
738 if (
lw.k_proj_f32_dev) {
cudaFree(
lw.k_proj_f32_dev);
lw.k_proj_f32_dev =
nullptr; }
739 if (
lw.v_proj_f32_dev) {
cudaFree(
lw.v_proj_f32_dev);
lw.v_proj_f32_dev =
nullptr; }
740 if (
lw.o_proj_f32_dev) {
cudaFree(
lw.o_proj_f32_dev);
lw.o_proj_f32_dev =
nullptr; }
741 if (
lw.gate_proj_f32_dev) {
cudaFree(
lw.gate_proj_f32_dev);
lw.gate_proj_f32_dev =
nullptr; }
742 if (
lw.up_proj_f32_dev) {
cudaFree(
lw.up_proj_f32_dev);
lw.up_proj_f32_dev =
nullptr; }
743 if (
lw.down_proj_f32_dev) {
cudaFree(
lw.down_proj_f32_dev);
lw.down_proj_f32_dev =
nullptr; }
748 Logger::info(
"CPU-only build: free_layer_gpu_weights is a no-op for layer " + std::to_string(
layer_idx));
781 throw std::runtime_error(std::string(
ggml_type_name(
t)) +
" tensor with " + std::to_string(
n) +
782 " elements (not a multiple of " + std::to_string(width) +
")");
784 if (info.
size_in_bytes <
nb *
bsz)
throw std::runtime_error(
"legacy-quantised tensor is shorter than its element count implies");
794 static const std::vector<float>
table = [] {
795 std::vector<float>
t(65536);
806 for (
size_t i = 0;
i <
n; ++
i) {
808 std::memcpy(&
h,
p + 2 *
i, 2);
814 for (
size_t i = 0;
i <
n; ++
i) {
848 for (
size_t b = 0;
b <
nb; ++
b) {
851 std::memcpy(&
dh,
p, 2);
855 if (
five_bit) { std::memcpy(&qh,
p, 4);
p += 4; }
858 float*
y =
out +
b * 32;
859 for (
int j = 0;
j < 16; ++
j) {
860 int lo =
p[
j] & 0x0F,
hi =
p[
j] >> 4;
862 lo |= ((qh >>
j) & 1) << 4;
863 hi |= ((qh >> (
j + 16)) & 1) << 4;
868 y[
j] =
static_cast<float>(
lo - offset) * d +
m;
869 y[
j + 16] =
static_cast<float>(
hi - offset) * d +
m;
871 y[
j] =
static_cast<float>(
lo - offset) * d;
872 y[
j + 16] =
static_cast<float>(
hi - offset) * d;
880 Logger::info(
"Mapping GGUF weights to model fields (ULTRA-OPTIMIZED VERSION)...");
885 if (
gguf.mapped_tensor_data !=
nullptr &&
gguf.mapped_tensor_data_size > 0) {
888 Logger::info(
"map_gguf_weights: Using mmap mode (ZERO-COPY). Size: " +
889 std::to_string(
gguf.mapped_tensor_data_size) +
" bytes.");
890 }
else if (!
gguf.tensor_data.empty()) {
892 Logger::info(
"map_gguf_weights: Using non-mmap mode. Size: " +
893 std::to_string(
gguf.tensor_data.size()) +
" bytes.");
895 Logger::error(
"GGUF tensor data is not available. Cannot map weights.");
900 Logger::info(
"Processing " + std::to_string(
num_tensors) +
" tensors with ultra-optimized parallel mapping...");
903 std::vector<std::pair<std::string, GGUFTensorInfo>>
tensor_pairs;
905 for (
const auto&
pair :
gguf.tensor_infos_map) {
936 if (
name[0] ==
'o' ||
name[0] ==
't') {
938 }
else if (
name.size() > 4 &&
name[0] ==
'b' &&
name[1] ==
'l' &&
name[2] ==
'k' &&
name[3] ==
'.') {
1013 switch (info.
type) {
1067 }
catch (
const std::exception&
e) {
1075 #pragma omp parallel for schedule(static) if(model.layers.size() > 4)
1090 if (
last_dot == std::string::npos)
continue;
1095 #define LEGACY_OR_THROW(target_f32) \
1097 if (!dequant_legacy_to_f32(info, tensor_data_ptr, target_f32)) \
1098 throw std::runtime_error(name + ": unsupported tensor type " + ggml_type_name(info.type)); \
1100 #define FAST_COPY_WEIGHT(target_vec, block_type) \
1101 target_vec.resize(info.size_in_bytes / sizeof(block_type)); \
1102 std::memcpy(target_vec.data(), tensor_data_ptr, info.size_in_bytes);
1108 if (
name_len > 10 &&
name.find(
"attn_") != std::string::npos) {
1109 if (
name.find(
"attn_q.weight") != std::string::npos) {
1110 switch (info.
type) {
1119 std::to_string(
layer.q_proj_f32.size()) +
1120 " into layer_idx=" + std::to_string(
layer_idx));
1124 }
else if (
name.find(
"attn_k.weight") != std::string::npos) {
1125 switch (info.
type) {
1135 }
else if (
name.find(
"attn_v.weight") != std::string::npos) {
1136 switch (info.
type) {
1146 }
else if (
name.find(
"attn_output.weight") != std::string::npos) {
1147 switch (info.
type) {
1157 }
else if (
name.find(
"attn_norm.weight") != std::string::npos) {
1162 }
else if (
name_len > 10 &&
name.find(
"ffn_") != std::string::npos) {
1163 if (
name.find(
"ffn_gate_inp.weight") != std::string::npos) {
1168 }
else if (
name.find(
"_exps.weight") != std::string::npos) {
1169 std::vector<float>&
dst =
name.find(
"ffn_gate_exps") != std::string::npos ?
layer.moe_gate_exps_f32
1170 :
name.find(
"ffn_up_exps") != std::string::npos ?
layer.moe_up_exps_f32
1171 :
layer.moe_down_exps_f32;
1174 throw std::runtime_error(
name +
": MoE expert stacks must be F32, F16 or Q4_0/Q4_1/Q5_0/Q5_1 (got " +
1176 }
else if (
name.find(
"ffn_gate.weight") != std::string::npos) {
1177 switch (info.
type) {
1187 }
else if (
name.find(
"ffn_up.weight") != std::string::npos) {
1188 switch (info.
type) {
1198 }
else if (
name.find(
"ffn_down.weight") != std::string::npos) {
1199 switch (info.
type) {
1209 }
else if (
name.find(
"ffn_norm.weight") != std::string::npos) {
1216 #undef FAST_COPY_WEIGHT
1217 #undef LEGACY_OR_THROW
1220 }
catch (
const std::exception&
e) {
1228 std::to_string(
num_tensors) +
" tensors processed successfully (errors: " +
1229 std::to_string(
error_count.load()) +
") with ultra-optimized parallel mapping");
1232 throw std::runtime_error(
"GGUF weight mapping failed for " + std::to_string(
error_count.load()) +
1239 Logger::info(
"CPU-only build: ensure_f32_concatenated_weights_loaded is a no-op");
1243 Logger::info(
"CPU-only build: ensure_bf16_concatenated_weights_loaded is a no-op");
1247 Logger::info(
"CPU-only build: free_bf16_concatenated_weights is a no-op");
static void warning(const std::string &message)
static void info(const std::string &message)
static void error(const std::string &message)
Main transformer model class for TinyLlama.
void free_layer_gpu_weights(int layer_idx)
bool f32_concatenated_weights_loaded_
std::vector< block_q6_K > embed_tokens_q6k
bool dequantize_all_if_small(size_t max_params)
void ensure_up_proj_dequantized(int layer_idx)
std::vector< float > final_norm_f32
void free_bf16_concatenated_weights()
void ensure_v_proj_dequantized(int layer_idx)
std::vector< block_q4_K > lm_head_q4k
std::vector< block_q6_K > lm_head_q6k
void ensure_layer_weights_on_gpu(int layer_idx)
std::vector< block_q5_K > lm_head_q5k
void ensure_embed_tokens_dequantized()
std::vector< LayerWeights > layers
std::vector< block_q8_0 > embed_tokens_q8_0
void ensure_o_proj_dequantized(int layer_idx)
void clear_layer_dequantized_weights(int layer_idx)
std::vector< block_q4_K > embed_tokens_q4k
void ensure_k_proj_dequantized(int layer_idx)
std::vector< block_q8_0 > lm_head_q8_0
std::vector< uint16_t > lm_head
void ensure_f32_concatenated_weights_loaded()
std::vector< block_q5_K > embed_tokens_q5k
std::vector< uint16_t > embed_tokens
std::vector< block_q8_K > embed_tokens_q8k
void ensure_bf16_concatenated_weights_loaded()
void ensure_q_proj_dequantized(int layer_idx)
void ensure_down_proj_dequantized(int layer_idx)
void ensure_gate_proj_dequantized(int layer_idx)
std::vector< float > embed_tokens_f32
void ensure_lm_head_dequantized()
std::vector< float > lm_head_f32
std::vector< block_q8_K > lm_head_q8k
void convert_fp32_to_bf16_cuda(const float *fp32_in_dev, uint16_t *bf16_out_dev, size_t n_elements, cudaStream_t stream)
Type definitions for GGML (Georgi Gerganov Machine Learning) library.
GGMLType
Enumeration of GGML tensor data types.
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.
float bfloat16_to_float32(uint16_t b16)
Template get(const std::string &id)
void dequantize_q4_k_m(const block_q4_K *qblock, float *output, int num_weights_in_block, bool log_this_block)
void dequantize_vector_q5k_to_f32(const std::vector< block_q5_K > &q_weights, std::vector< float > &f32_weights, size_t total_num_elements)
Dequantizes a vector of Q5_K blocks to float32 (total_num_elements a multiple of GGML_QK_K)
size_t ggml_type_size(GGMLType type)
Gets the size in bytes of a GGML type.
const char * ggml_type_name(GGMLType type)
Gets the string name of a GGML type.
void dequantize_q5_k(const block_q5_K *qblock, float *output)
void dequantize_vector_q6k_to_f32(const std::vector< block_q6_K > &q_weights, std::vector< float > &f32_weights, size_t total_num_elements, int log_first_n_blocks)
Dequantizes a vector of Q6_K blocks to a vector of float32.
float fp16_to_fp32(uint16_t h, bool is_gguf_scale_field)
Converts a 16-bit floating point number to 32-bit float.
void dequantize_vector_q8_0_to_f32(const std::vector< block_q8_0 > &q_weights, std::vector< float > &f32_weights, size_t total_num_elements, int log_first_n_blocks)
Dequantizes a vector of Q8_0 blocks to a vector of float32.
void dequantize_vector_q4k_to_f32(const std::vector< block_q4_K > &q_weights, std::vector< float > &f32_weights, size_t total_num_elements, int log_first_n_blocks)
Dequantizes a vector of Q4_K blocks to a vector of float32.
void dequantize_q8_0_block(const block_q8_0 *qblock, float *output)
Dequantizes a Q8_0 block to float32.
void dequantize_q8_k(const std::vector< block_q8_K > &q_data, std::vector< float > &x, int n, bool log_this_block)
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.
Complete representation of a GGUF file's contents.
Information about a tensor stored in a GGUF file.
Structure holding all weights for a single transformer layer.
int num_cpu_offload_layers
bool enable_memory_efficient_layers
4-bit K-quantized block structure
5-bit K-quantized block structure (ggml's block_q5_K)
6-bit K-quantized block structure
Simple 8-bit quantized block structure.
8-bit K-quantized block structure with block sums
std::vector< float > bf16vec_to_float_vec(const std::vector< uint16_t > &v_bf16)
#define FAST_COPY_WEIGHT(target_vec, block_type)
void map_gguf_weights(const GGUFData &gguf, TinyLlamaModel &model)
#define EMBER_RECOVERABLE(w)
bool dequant_legacy_to_f32(const GGUFTensorInfo &info, const uint8_t *src, std::vector< float > &out)
static const float * fp16_table()
bool dequant_span_to_f32(GGMLType t, const uint8_t *src, size_t first, size_t n, float *out)
#define LEGACY_OR_THROW(target_f32)