mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-19 17:24:57 +02:00
qwen4exp: shrink the PLE hparams storage
llama_hparams is held by value inside llm_graph_params and every llm_graph_input_*, and llm_graph_params is a stack local in graph_reserve and process_ubatch, so its width is paid on every worker thread stack. is_ple_impl spent 2048 bytes carrying 512 bits. It is the one per-layer flag that is not moved through the loader's uint32 array templates, so a bitset costs nothing in call sites and also removes the uninitialized read that non-qwen4exp archs had, since nothing filled the array for them. The PLE head offsets and vocab sizes are token-space indices; the gather that consumes them already truncates to int32, so 64-bit storage was never reachable. The gguf arrays stay uint64 for file compatibility and are narrowed on load. sizeof(llama_hparams) 34440 -> 31944, sizeof(llm_graph_params) 34872 -> 32376.
This commit is contained in:
committed by
Daniel Han
parent
1caf6c5711
commit
c3259772c7
+10
-3
@@ -3,6 +3,7 @@
|
||||
#include "llama.h"
|
||||
|
||||
#include <array>
|
||||
#include <bitset>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
@@ -283,10 +284,16 @@ struct llama_hparams {
|
||||
uint32_t ple_eos_token_id = 0;
|
||||
// the id the PLE hash stands in at image positions; 0 makes the loader fall back to EOS
|
||||
uint32_t ple_image_token_id = 0;
|
||||
std::array<uint32_t, LLAMA_MAX_LAYERS> is_ple_impl;
|
||||
// unlike is_swa_impl and friends this is never read or written as a per-layer gguf array
|
||||
// (the file lists PLE layer indices), so it is not tied to the loader's uint32 array type
|
||||
// and can hold one bit per layer instead of one word
|
||||
std::bitset<LLAMA_MAX_LAYERS> is_ple_impl;
|
||||
// the hash multipliers reach ~2e13 and have to stay 64-bit
|
||||
std::array<uint64_t, LLAMA_MAX_PLE_NGRAM> ple_layer_multipliers;
|
||||
std::array<uint64_t, LLAMA_MAX_PLE_HEADS> ple_head_offsets;
|
||||
std::array<uint64_t, LLAMA_MAX_PLE_HEADS> ple_head_vocab_sizes;
|
||||
// head offsets and vocab sizes are token-space indices; the gather that consumes them
|
||||
// truncates to int32, so 64-bit storage could never have been used
|
||||
std::array<uint32_t, LLAMA_MAX_PLE_HEADS> ple_head_offsets;
|
||||
std::array<uint32_t, LLAMA_MAX_PLE_HEADS> ple_head_vocab_sizes;
|
||||
|
||||
bool is_ple(uint32_t il) const;
|
||||
|
||||
|
||||
+15
-4
@@ -33,7 +33,7 @@ void llama_model_qwen4exp::load_arch_hparams(llama_model_loader & ml) {
|
||||
ml.get_key_or_arr(LLM_KV_ATTENTION_COMPRESS_RATIOS, hparams.dsv4_compress_ratios, hparams.n_layer_all, false);
|
||||
|
||||
// PLE n-gram hash embeddings; if the key group is absent every field stays zero
|
||||
std::fill(hparams.is_ple_impl.begin(), hparams.is_ple_impl.end(), 0);
|
||||
hparams.is_ple_impl.reset();
|
||||
hparams.ple_n_heads = 0;
|
||||
|
||||
uint32_t n_ple = 0;
|
||||
@@ -43,7 +43,7 @@ void llama_model_qwen4exp::load_arch_hparams(llama_model_loader & ml) {
|
||||
ml.get_arr(LLM_KV_PLE_LAYERS, ple_layers);
|
||||
for (uint32_t il : ple_layers) {
|
||||
GGML_ASSERT(il < hparams.n_layer_all);
|
||||
hparams.is_ple_impl[il] = 1;
|
||||
hparams.is_ple_impl.set(il);
|
||||
}
|
||||
|
||||
ml.get_key(LLM_KV_PLE_NGRAM_SIZE, hparams.ple_ngram_size);
|
||||
@@ -60,8 +60,19 @@ void llama_model_qwen4exp::load_arch_hparams(llama_model_loader & ml) {
|
||||
GGML_ASSERT(hparams.ple_n_heads > 0 && hparams.ple_n_heads <= LLAMA_MAX_PLE_HEADS);
|
||||
|
||||
ml.get_arr(LLM_KV_PLE_LAYER_MULTIPLIERS, hparams.ple_layer_multipliers);
|
||||
ml.get_arr(LLM_KV_PLE_HEAD_OFFSETS, hparams.ple_head_offsets);
|
||||
ml.get_arr(LLM_KV_PLE_HEAD_VOCAB_SIZES, hparams.ple_head_vocab_sizes);
|
||||
|
||||
// the file writes the head ranges as uint64 arrays, so read them at that width and
|
||||
// narrow; hparams keeps them at the int32 width the row gather actually uses
|
||||
std::array<uint64_t, LLAMA_MAX_PLE_HEADS> head_offsets = {};
|
||||
std::array<uint64_t, LLAMA_MAX_PLE_HEADS> head_vocab_sizes = {};
|
||||
ml.get_arr(LLM_KV_PLE_HEAD_OFFSETS, head_offsets);
|
||||
ml.get_arr(LLM_KV_PLE_HEAD_VOCAB_SIZES, head_vocab_sizes);
|
||||
for (uint32_t h = 0; h < hparams.ple_n_heads; ++h) {
|
||||
GGML_ASSERT(head_offsets[h] + head_vocab_sizes[h] <= INT32_MAX &&
|
||||
"PLE head range does not fit the int32 row index");
|
||||
hparams.ple_head_offsets[h] = (uint32_t) head_offsets[h];
|
||||
hparams.ple_head_vocab_sizes[h] = (uint32_t) head_vocab_sizes[h];
|
||||
}
|
||||
}
|
||||
|
||||
// linear attention everywhere except every full_attention_interval-th layer
|
||||
|
||||
Reference in New Issue
Block a user