ember.cpp 0.1.0
C++ inference engine for Llama-family and paperkiln models (CPU, CUDA, WebAssembly)
Loading...
Searching...
No Matches
CPUBatchProcessor Class Reference

#include <cpu_batch_processor.h>

Collaboration diagram for CPUBatchProcessor:
Collaboration graph

Public Member Functions

 CPUBatchProcessor (TinyLlamaModel *model)
 
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)
 

Private Attributes

TinyLlamaModel * model_
 

Detailed Description

Definition at line 7 of file cpu_batch_processor.h.

Constructor & Destructor Documentation

◆ CPUBatchProcessor()

CPUBatchProcessor::CPUBatchProcessor ( TinyLlamaModel *  model)
explicit

Definition at line 9 of file cpu_batch_processor.cpp.

9: model_(model) {}
TinyLlamaModel * model_

Member Function Documentation

◆ forward_cpu_batch()

std::vector< float > CPUBatchProcessor::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 
)

Definition at line 11 of file cpu_batch_processor.cpp.

17 {
18
20 Logger::error("[CPU_BATCH_FWD] Input size mismatch. Expected: " +
21 std::to_string((size_t)num_tokens_in_batch * model_->config_.hidden_size) + " Got: " +
22 std::to_string(batch_input_activations.size()));
23 return {};
24 }
25
30 if (n_heads == 0) {
31 Logger::error("[CPU_BATCH_FWD] Error: num_attention_heads is zero.");
32 return {};
33 }
34 int head_dim = hs / n_heads;
38 float attention_scale = 1.0f / SAFE_SQRT(static_cast<float>(head_dim));
39
41
42 std::vector<int> sequence_indices(num_tokens_in_batch);
44
45 if (!prompt_lengths.empty()) {
46 int token_offset = 0;
47 for (size_t seq_idx = 0; seq_idx < prompt_lengths.size(); ++seq_idx) {
48 for (int pos = 0; pos < prompt_lengths[seq_idx]; ++pos) {
50 Logger::error("[CPU_BATCH_FWD] Token offset exceeded num_tokens_in_batch");
51 return {};
52 }
56 }
57 }
58 } else {
62 }
63 }
64
65 for (int l = 0; l < num_cpu_layers_to_process; ++l) {
73
74 const auto& lw = model_->layers[l];
75
76 std::vector<float> batch_x_norm1(current_batch_activations.size());
77 const std::vector<float>& w_input_norm_vec =
78 lw.input_layernorm_f32.empty()
79 ? bf16vec_to_float_vec(lw.input_layernorm)
80 : lw.input_layernorm_f32;
82
84
85 std::vector<float> q_batch((size_t)num_tokens_in_batch * hs);
86 std::vector<float> k_batch((size_t)num_tokens_in_batch * n_kv_heads * head_dim);
87 std::vector<float> v_batch((size_t)num_tokens_in_batch * n_kv_heads * head_dim);
88
89 if (!lw.q_proj_f32.empty()) {
91 } else if (!lw.q_proj_q8_0.empty()) {
93 } else if (!lw.q_proj_q6k.empty()) {
95 } else if (!lw.q_proj_q4k.empty()) {
97 } else {
98 Logger::error("[CPU_BATCH_FWD] Layer " + std::to_string(l) + ": No Q proj weights found for CPU");
99 return {};
100 }
101
102 if (!lw.k_proj_f32.empty()) {
104 } else if (!lw.k_proj_q8_0.empty()) {
106 } else if (!lw.k_proj_q6k.empty()) {
108 } else if (!lw.k_proj_q4k.empty()) {
110 } else {
111 Logger::error("[CPU_BATCH_FWD] Layer " + std::to_string(l) + ": No K proj weights found for CPU");
112 return {};
113 }
114
115 if (!lw.v_proj_f32.empty()) {
117 } else if (!lw.v_proj_q8_0.empty()) {
119 } else if (!lw.v_proj_q6k.empty()) {
121 } else if (!lw.v_proj_q4k.empty()) {
123 } else {
124 Logger::error("[CPU_BATCH_FWD] Layer " + std::to_string(l) + ": No V proj weights found for CPU");
125 return {};
126 }
127
128 if (!prompt_lengths.empty()) {
129 for (int t = 0; t < num_tokens_in_batch; ++t) {
132
134 Logger::warning("[CPU_BATCH_FWD] Token " + std::to_string(t) + " (seq=" + std::to_string(seq_idx) +
135 ", pos=" + std::to_string(current_token_pos) + ") is out of range. Skipping RoPE.");
136 continue;
137 }
138
139 std::vector<float> q_token(hs);
140 std::vector<float> k_token(n_kv_heads * head_dim);
141
142 std::copy(q_batch.begin() + (size_t)t * hs,
143 q_batch.begin() + (size_t)(t + 1) * hs,
144 q_token.begin());
145 std::copy(k_batch.begin() + (size_t)t * n_kv_heads * head_dim,
146 k_batch.begin() + (size_t)(t + 1) * n_kv_heads * head_dim,
147 k_token.begin());
148
151
152 std::copy(q_token.begin(), q_token.end(), q_batch.begin() + (size_t)t * hs);
153 std::copy(k_token.begin(), k_token.end(), k_batch.begin() + (size_t)t * n_kv_heads * head_dim);
154 }
155 } else {
158 }
159
160 if (kv_cache) {
161 if (!prompt_lengths.empty()) {
164 } else {
167 }
168 }
169
170 std::vector<float> batch_attn_output((size_t)num_tokens_in_batch * hs);
171
172 if (kv_cache && static_cast<size_t>(l) < kv_cache->layers.size()) {
173 if (!prompt_lengths.empty()) {
177 kv_cache->max_seq_len_config_);
178 } else {
182 }
183 } else if (kv_cache) {
184 Logger::error("[CPU_BATCH_FWD] Layer " + std::to_string(l) +
185 " is out of bounds for KV Cache access during attention. KVCache layers size: " +
186 std::to_string(kv_cache->layers.size()) +
187 ". Filling attention output with zeros.");
188 std::fill(batch_attn_output.begin(), batch_attn_output.end(), 0.0f);
189 } else {
190 Logger::error("[CPU_BATCH_FWD] KV Cache is null, cannot perform attention for layer " + std::to_string(l) +
191 ". Filling attention output with zeros.");
192 std::fill(batch_attn_output.begin(), batch_attn_output.end(), 0.0f);
193 }
194
195 std::vector<float> batch_attn_proj_out((size_t)num_tokens_in_batch * hs);
196 if(!lw.o_proj_f32.empty()) {
198 } else if (!lw.o_proj_q8_0.empty()) {
200 } else if (!lw.o_proj_q6k.empty()) {
202 } else if (!lw.o_proj_q4k.empty()) {
204 } else {
205 Logger::error("[CPU_BATCH_FWD] Layer " + std::to_string(l) + ": No O proj weights found for CPU");
206 return {};
207 }
208
209 for(size_t i=0; i < current_batch_activations.size(); ++i) {
211 }
212
214 std::vector<float> batch_x_norm2(current_batch_activations.size());
215 const std::vector<float>& w_post_attn_norm_vec =
216 lw.post_attention_layernorm_f32.empty()
217 ? bf16vec_to_float_vec(lw.post_attention_layernorm)
218 : lw.post_attention_layernorm_f32;
219
221
222 std::vector<float> batch_mlp_down_proj_out((size_t)num_tokens_in_batch * hs);
223 if (model_->config_.num_experts > 0 && !lw.moe_gate_exps_f32.empty()) {
224 // Mixture-of-experts FFN, token by token (utils.cpp moe_ffn_f32_cpu).
225 #pragma omp parallel for schedule(static)
226 for (int t = 0; t < num_tokens_in_batch; ++t)
228 model_->config_.num_experts_used, lw.moe_router_f32.data(), lw.moe_gate_exps_f32.data(),
229 lw.moe_up_exps_f32.data(), lw.moe_down_exps_f32.data(),
230 batch_mlp_down_proj_out.data() + (size_t)t * hs);
231 } else {
232 std::vector<float> batch_gate_proj_out((size_t)num_tokens_in_batch * is);
233 std::vector<float> batch_up_proj_out((size_t)num_tokens_in_batch * is);
234
235 if (!lw.gate_proj_f32.empty()) {
237 } else if (!lw.gate_proj_q8_0.empty()) {
239 } else if (!lw.gate_proj_q6k.empty()) {
241 } else if (!lw.gate_proj_q4k.empty()) {
243 } else {
244 Logger::error("[CPU_BATCH_FWD] Layer " + std::to_string(l) + ": No gate_proj weights found for CPU");
245 return {};
246 }
247
248 if (!lw.up_proj_f32.empty()) {
250 } else if (!lw.up_proj_q8_0.empty()) {
252 } else if (!lw.up_proj_q6k.empty()) {
254 } else if (!lw.up_proj_q4k.empty()) {
256 } else {
257 Logger::error("[CPU_BATCH_FWD] Layer " + std::to_string(l) + ": No up_proj weights found for CPU");
258 return {};
259 }
260
261 std::vector<float> batch_swiglu_out((size_t)num_tokens_in_batch * is);
262 for (size_t i = 0; i < batch_gate_proj_out.size(); ++i) {
264 float silu_gate_val = gate_val / (1.0f + std::exp(-gate_val));
266 }
267
268 if (!lw.down_proj_f32.empty()) {
270 } else if (!lw.down_proj_q8_0.empty()) {
272 } else if (!lw.down_proj_q6k.empty()) {
274 } else if (!lw.down_proj_q4k.empty()) {
276 } else {
277 Logger::error("[CPU_BATCH_FWD] Layer " + std::to_string(l) + ": No down_proj weights found for CPU");
278 return {};
279 }
280 } // dense FFN
281
282 for(size_t i = 0; i < current_batch_activations.size(); ++i) {
284 }
285 }
286
287 if (kv_cache && num_tokens_in_batch > 0) {
289 }
291}
#define SAFE_SQRT(x)
static void warning(const std::string &message)
Definition logger.cpp:139
static void error(const std::string &message)
Definition logger.cpp:143
void ensure_up_proj_dequantized(int layer_idx)
void ensure_v_proj_dequantized(int layer_idx)
std::vector< std::pair< float, float > > precomputed_freqs_cis_
Definition model.h:694
std::vector< LayerWeights > layers
Definition model.h:587
ModelConfig config_
Definition model.h:573
void ensure_o_proj_dequantized(int layer_idx)
void ensure_k_proj_dequantized(int layer_idx)
void ensure_q_proj_dequantized(int layer_idx)
void ensure_down_proj_dequantized(int layer_idx)
void ensure_gate_proj_dequantized(int layer_idx)
void attention_batch_cpu_sequence_aware(const std::vector< float > &q_batch_roped, KVCacheLayer &current_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, const std::vector< int > &sequence_indices, const std::vector< int > &position_in_sequence, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, int max_seq_len_per_sequence)
void attention_batch_cpu(const std::vector< float > &q_batch_roped, KVCacheLayer &current_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, int start_pos_in_sequence, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, float softcap)
void update_kv_cache_batch_cpu_sequence_aware(KVCache *kv_cache, int layer_idx, const std::vector< float > &k_batch_for_layer, const std::vector< float > &v_batch_for_layer, int num_tokens_in_batch, const std::vector< int > &sequence_indices, const std::vector< int > &position_in_sequence, int num_kv_heads, int head_dim)
void update_kv_cache_batch_cpu(KVCache *kv_cache, int layer_idx, const std::vector< float > &k_batch_for_layer, const std::vector< float > &v_batch_for_layer, int num_tokens_in_batch, int start_pos_in_sequence, int num_kv_heads, int head_dim)
size_t j
int hidden_size
Definition model.h:83
float rms_norm_eps
Definition model.h:90
int num_attention_heads
Definition model.h:85
int intermediate_size
Definition model.h:84
bool is_gguf_file_loaded
Definition model.h:103
int num_experts_used
Definition model.h:108
int num_key_value_heads
Definition model.h:86
int num_experts
Definition model.h:107
int max_position_embeddings
Definition model.h:89
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)
Definition utils.cpp:428
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)
Definition utils.cpp:1155
std::vector< float > bf16vec_to_float_vec(const std::vector< uint16_t > &v_bf16)
Definition utils.cpp:199
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)
Definition utils.cpp:1036
void apply_rope_batch_cpu(std::vector< float > &q_batch, std::vector< float > &k_batch, int num_tokens, int num_q_heads, int num_kv_heads, int head_dim, int start_pos_in_sequence, const std::vector< std::pair< float, float > > &all_freqs_cis, int max_pos_embeddings, bool use_adjacent_pairing)
Definition utils.cpp:491
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)
Definition utils.cpp:872
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)
Definition utils.cpp:1117
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)
Definition utils.cpp:709
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)
Definition utils.cpp:613

References apply_rope_batch_cpu(), apply_rope_vector(), attention_batch_cpu(), attention_batch_cpu_sequence_aware(), bf16vec_to_float_vec(), TinyLlamaModel::config_, TinyLlamaModel::ensure_down_proj_dequantized(), TinyLlamaModel::ensure_gate_proj_dequantized(), TinyLlamaModel::ensure_k_proj_dequantized(), TinyLlamaModel::ensure_o_proj_dequantized(), TinyLlamaModel::ensure_q_proj_dequantized(), TinyLlamaModel::ensure_up_proj_dequantized(), TinyLlamaModel::ensure_v_proj_dequantized(), Logger::error(), ModelConfig::hidden_size, ModelConfig::intermediate_size, ModelConfig::is_gguf_file_loaded, j, TinyLlamaModel::layers, matmul_f32_f32_batch_cpu(), matmul_q4k_f32_batch_cpu(), matmul_q6k_f32_batch_cpu(), matmul_q8_0_f32_batch_cpu(), ModelConfig::max_position_embeddings, model_, moe_ffn_f32_cpu(), ModelConfig::num_attention_heads, ModelConfig::num_experts, ModelConfig::num_experts_used, ModelConfig::num_key_value_heads, pos, TinyLlamaModel::precomputed_freqs_cis_, ModelConfig::rms_norm_eps, rmsnorm_batch_cpu(), SAFE_SQRT, update_kv_cache_batch_cpu(), update_kv_cache_batch_cpu_sequence_aware(), and Logger::warning().

Member Data Documentation

◆ model_

TinyLlamaModel* CPUBatchProcessor::model_
private

Definition at line 20 of file cpu_batch_processor.h.

Referenced by forward_cpu_batch().


The documentation for this class was generated from the following files: