15 const float *A,
const float *B,
const float *bias,
float *
C,
16 int M,
int N,
int K,
int output_begin,
int output_end);
18 const float *input,
const float *gamma,
float *output,
float *rstd_cache,
19 int tokens,
int d_model,
int aligned_embed_dim,
float eps);
27} ck_gemma4_block_q5_K;
29#define CK_GEMMA4_MAX_EMBED_DIM 16384
33 uint32_t bits = ((uint32_t)v) << 16;
35 memcpy(&out, &bits,
sizeof(out));
45 __m256 c1 = _mm256_setzero_ps();
46 __m256 c2 = _mm256_setzero_ps();
47 __m256 c3 = _mm256_setzero_ps();
48 __m256 c4 = _mm256_setzero_ps();
49#define CK_GEMMA4_LOAD_BF16(p) _mm256_castsi256_ps(_mm256_slli_epi32( \
50 _mm256_cvtepu16_epi32(_mm_loadu_si128((const __m128i *)(p))), 16))
51 for (; i + 32 <= n; i += 32) {
52 c1 = _mm256_add_ps(_mm256_mul_ps(CK_GEMMA4_LOAD_BF16(x + i),
53 CK_GEMMA4_LOAD_BF16(y + i)), c1);
54 c2 = _mm256_add_ps(_mm256_mul_ps(CK_GEMMA4_LOAD_BF16(x + i + 8),
55 CK_GEMMA4_LOAD_BF16(y + i + 8)), c2);
56 c3 = _mm256_add_ps(_mm256_mul_ps(CK_GEMMA4_LOAD_BF16(x + i + 16),
57 CK_GEMMA4_LOAD_BF16(y + i + 16)), c3);
58 c4 = _mm256_add_ps(_mm256_mul_ps(CK_GEMMA4_LOAD_BF16(x + i + 24),
59 CK_GEMMA4_LOAD_BF16(y + i + 24)), c4);
61#undef CK_GEMMA4_LOAD_BF16
62 c1 = _mm256_add_ps(_mm256_add_ps(c1, c3), _mm256_add_ps(c2, c4));
63 __m128 g = _mm_add_ps(_mm256_extractf128_ps(c1, 1), _mm256_castps256_ps128(c1));
64 g = _mm_add_ps(g, _mm_movehl_ps(g, g));
65 g = _mm_add_ss(g, _mm_movehdup_ps(g));
66 sum = (double)_mm_cvtss_f32(g);
76 if (x <= -10.0f)
return 0.0f;
77 if (x >= 10.0f)
return x;
79 const float c0 = 0.7978845608028654f;
80 const float c1 = 0.044715f;
81 const float y = 0.5f * x * (1.0f + tanhf(c0 * x * (1.0f + c1 * x * x)));
87 sc[0] = scales[0] & 0x3F;
88 sc[1] = scales[1] & 0x3F;
89 sc[2] = scales[2] & 0x3F;
90 sc[3] = scales[3] & 0x3F;
92 m[0] = scales[4] & 0x3F;
93 m[1] = scales[5] & 0x3F;
94 m[2] = scales[6] & 0x3F;
95 m[3] = scales[7] & 0x3F;
97 sc[4] = (scales[8] & 0x0F) | ((scales[0] >> 6) << 4);
98 sc[5] = (scales[9] & 0x0F) | ((scales[1] >> 6) << 4);
99 sc[6] = (scales[10] & 0x0F) | ((scales[2] >> 6) << 4);
100 sc[7] = (scales[11] & 0x0F) | ((scales[3] >> 6) << 4);
102 m[4] = (scales[8] >> 4) | ((scales[4] >> 6) << 4);
103 m[5] = (scales[9] >> 4) | ((scales[5] >> 6) << 4);
104 m[6] = (scales[10] >> 4) | ((scales[6] >> 6) << 4);
105 m[7] = (scales[11] >> 4) | ((scales[7] >> 6) << 4);
110 const uint8_t *ql = block->qs + (subblock / 2) * 32;
111 const uint8_t low = (subblock & 1) ? (uint8_t)(ql[i] >> 4) : (uint8_t)(ql[i] & 0x0F);
112 const uint8_t high = (block->qh[i] & (uint8_t)(1u << subblock)) ? 16u : 0u;
113 return (uint8_t)(low | high);
123 for (
int s = 0; s < 8; ++s) {
124 const float scale = d * (float)sc[s];
125 const float minv = dmin * (float)m[s];
126 for (
int i = 0; i < 32; ++i) {
135 for (
int i = 0; i < n; ++i) {
136 ss += (double)x[i] * (
double)x[i];
138 const float scale = 1.0f / sqrtf((
float)(ss / (
double)n) + eps);
139 for (
int i = 0; i < n; ++i) {
140 out[i] = x[i] * scale * gamma[i];
145 float *per_layer_input;
147 const int32_t *token_ids;
148 const void *per_layer_token_emb;
149 const uint16_t *per_layer_model_proj;
150 const float *per_layer_proj_norm;
156} ck_gemma4_prepare_args_t;
160 const ck_gemma4_prepare_args_t *args =
161 (
const ck_gemma4_prepare_args_t *)opaque;
162 const ck_gemma4_block_q5_K *token_blocks =
163 (
const ck_gemma4_block_q5_K *)args->per_layer_token_emb;
164 const size_t token_blocks_per_row = (size_t)args->num_layers;
165 const float token_scale = sqrtf((
float)args->per_layer_dim);
166 const float model_scale = 1.0f / sqrtf((
float)args->embed_dim);
167 const float mix_scale = 0.7071067811865475f;
168 float token_vec[
QK_K];
169 float proj_vec[
QK_K];
170 float proj_normed[
QK_K];
172 for (
int t = begin; t <
end; ++t) {
173 const int token = args->token_ids[t];
174 if (token < 0 || token >= args->vocab_size)
continue;
175 const float *h = args->hidden + (size_t)t * (
size_t)args->embed_dim;
176 uint16_t rounded_hidden[args->embed_dim];
177 for (
int j = 0; j < args->embed_dim; ++j) {
180 for (
int layer = 0; layer < args->num_layers; ++layer) {
181 float *dst = args->per_layer_input +
182 ((size_t)t * (
size_t)args->num_layers + (size_t)layer) *
183 (size_t)args->per_layer_dim;
184 const ck_gemma4_block_q5_K *tok_block = token_blocks +
185 (size_t)
token * token_blocks_per_row + (
size_t)layer;
187 for (
int i = 0; i < args->per_layer_dim; ++i) {
188 token_vec[i] *= token_scale;
191 const uint16_t *model_proj_base = args->per_layer_model_proj +
192 (size_t)layer * (
size_t)args->per_layer_dim *
193 (size_t)args->embed_dim;
194 for (
int i = 0; i < args->per_layer_dim; ++i) {
195 const uint16_t *row = model_proj_base +
196 (size_t)i * (
size_t)args->embed_dim;
198 proj_vec[i] = acc * model_scale;
201 proj_vec, args->per_layer_proj_norm, proj_normed,
202 args->per_layer_dim, args->eps);
203 for (
int i = 0; i < args->per_layer_dim; ++i) {
204 dst[i] = (token_vec[i] + proj_normed[i]) * mix_scale;
212 const ck_gemma4_prepare_args_t *args =
213 (
const ck_gemma4_prepare_args_t *)opaque;
214 const uint16_t *token_embeddings =
215 (
const uint16_t *)args->per_layer_token_emb;
216 const float token_scale = sqrtf((
float)args->per_layer_dim);
217 const float model_scale = 1.0f / sqrtf((
float)args->embed_dim);
218 const float mix_scale = 0.7071067811865475f;
219 float token_vec[
QK_K];
220 float proj_vec[
QK_K];
221 float proj_normed[
QK_K];
223 for (
int t = begin; t <
end; ++t) {
224 const int token = args->token_ids[t];
225 if (token < 0 || token >= args->vocab_size)
continue;
226 const float *h = args->hidden + (size_t)t * (
size_t)args->embed_dim;
227 uint16_t rounded_hidden[args->embed_dim];
228 for (
int j = 0; j < args->embed_dim; ++j) {
231 for (
int layer = 0; layer < args->num_layers; ++layer) {
232 float *dst = args->per_layer_input +
233 ((size_t)t * (
size_t)args->num_layers + (size_t)layer) *
234 (size_t)args->per_layer_dim;
235 const uint16_t *tok_row = token_embeddings +
236 ((size_t)
token * (
size_t)args->num_layers + (size_t)layer) *
237 (size_t)args->per_layer_dim;
238 for (
int i = 0; i < args->per_layer_dim; ++i) {
242 const uint16_t *model_proj_base = args->per_layer_model_proj +
243 (size_t)layer * (
size_t)args->per_layer_dim *
244 (size_t)args->embed_dim;
245 for (
int i = 0; i < args->per_layer_dim; ++i) {
246 const uint16_t *row = model_proj_base +
247 (size_t)i * (
size_t)args->embed_dim;
249 proj_vec[i] = acc * model_scale;
252 proj_vec, args->per_layer_proj_norm, proj_normed,
253 args->per_layer_dim, args->eps);
254 for (
int i = 0; i < args->per_layer_dim; ++i) {
255 dst[i] = (token_vec[i] + proj_normed[i]) * mix_scale;
262 int tokens,
ck_range_fn_t fn, ck_gemma4_prepare_args_t *args)
266 const char *disabled = getenv(
"CK_DISABLE_GEMMA4_PREPARE_PARALLEL");
267 if (disabled && disabled[0] && strcmp(disabled,
"0") != 0) active = 1;
268 if (active > tokens) active = tokens;
274 const int32_t *token_ids,
275 const void *per_layer_token_emb,
276 const uint16_t *per_layer_model_proj,
277 const float *per_layer_proj_norm,
285 if (!per_layer_input || !hidden || !token_ids || !per_layer_token_emb ||
286 !per_layer_model_proj || !per_layer_proj_norm || tokens <= 0 ||
292 ck_gemma4_prepare_args_t args = {
293 .per_layer_input = per_layer_input,
295 .token_ids = token_ids,
296 .per_layer_token_emb = per_layer_token_emb,
297 .per_layer_model_proj = per_layer_model_proj,
298 .per_layer_proj_norm = per_layer_proj_norm,
299 .num_layers = num_layers,
300 .embed_dim = embed_dim,
301 .per_layer_dim = per_layer_dim,
311 const int32_t *token_ids,
312 const uint16_t *per_layer_token_emb,
313 const uint16_t *per_layer_model_proj,
314 const float *per_layer_proj_norm,
322 if (!per_layer_input || !hidden || !token_ids || !per_layer_token_emb ||
323 !per_layer_model_proj || !per_layer_proj_norm || tokens <= 0 ||
329 if (per_layer_dim >
QK_K) {
332 ck_gemma4_prepare_args_t args = {
333 .per_layer_input = per_layer_input,
335 .token_ids = token_ids,
336 .per_layer_token_emb = per_layer_token_emb,
337 .per_layer_model_proj = per_layer_model_proj,
338 .per_layer_proj_norm = per_layer_proj_norm,
339 .num_layers = num_layers,
340 .embed_dim = embed_dim,
341 .per_layer_dim = per_layer_dim,
350 const float *per_layer_input;
351 const float *inp_gate;
353 const float *post_norm;
354 const float *out_scale;
361 const int *segment_lengths;
364} ck_gemma4_embed_args_t;
368 if (!args->segment_lengths)
return tokens > 1 ? 2 : 1;
370 for (
int segment = 0; segment < args->num_segments; ++segment) {
371 const int length = args->segment_lengths[segment];
373 if (length == 1 || (args->singleton_tail && segment == args->num_segments - 1)) {
385 const ck_gemma4_embed_args_t *args =
386 (
const ck_gemma4_embed_args_t *)opaque;
387 float gate_vec[
QK_K];
389 float branch_normed[4096];
390 for (
int t = begin; t <
end; ++t) {
391 float *h = args->hidden + (size_t)t * (
size_t)args->embed_dim;
392 const float *inp_vec = args->per_layer_input +
393 ((size_t)t * (
size_t)args->num_layers + (size_t)args->layer) *
394 (size_t)args->per_layer_dim;
398 h, args->inp_gate, NULL, gate_vec, row_group,
399 args->per_layer_dim, args->embed_dim, 0, args->per_layer_dim);
400 for (
int i = 0; i < args->per_layer_dim; ++i) {
405 gate_vec, args->proj, NULL, branch, row_group,
406 args->embed_dim, args->per_layer_dim, 0, args->embed_dim);
408 branch, args->post_norm, branch_normed, NULL,
409 1, args->embed_dim, args->embed_dim, args->eps);
410 const float layer_scale = args->out_scale ? args->out_scale[0] : 1.0f;
411 for (
int j = 0; j < args->embed_dim; ++j) {
412 h[j] = (h[j] + branch_normed[j]) * layer_scale;
418 const float *per_layer_input,
419 const float *inp_gate,
421 const float *post_norm,
422 const float *out_scale,
429 const int *segment_lengths,
433 if (!hidden || !per_layer_input || !inp_gate || !proj || !post_norm ||
434 tokens <= 0 || layer < 0 || layer >= num_layers || embed_dim <= 0 ||
435 per_layer_dim !=
QK_K || embed_dim > 4096 ||
436 (segment_lengths == NULL) != (num_segments == 0) ||
437 (singleton_tail != 0 && singleton_tail != 1)) {
440 if (segment_lengths) {
441 int remaining = tokens;
442 for (
int i = 0; i < num_segments; ++i) {
443 if (segment_lengths[i] < 0 || segment_lengths[i] > remaining)
return;
444 remaining -= segment_lengths[i];
446 if (remaining != 0)
return;
449 ck_gemma4_embed_args_t args = {
451 .per_layer_input = per_layer_input,
452 .inp_gate = inp_gate,
454 .post_norm = post_norm,
455 .out_scale = out_scale,
457 .num_layers = num_layers,
458 .embed_dim = embed_dim,
459 .per_layer_dim = per_layer_dim,
462 .segment_lengths = segment_lengths,
463 .num_segments = num_segments,
464 .singleton_tail = singleton_tail,
468 const char *disabled = getenv(
"CK_DISABLE_GEMMA4_EMBED_PARALLEL");
469 if (disabled && disabled[0] && strcmp(disabled,
"0") != 0) active = 1;
470 if (active > tokens) active = tokens;
480 if (!hidden || !scale || tokens <= 0 || embed_dim <= 0) {
484 const float s = scale[0];
485 const size_t n = (size_t)tokens * (
size_t)embed_dim;
486 for (
size_t i = 0; i < n; ++i) {
496 if (!logits || tokens <= 0 ||
vocab_size <= 0 || cap <= 0.0f) {
499 const float inv_cap = 1.0f / cap;
500 const size_t total = (size_t)tokens * (
size_t)
vocab_size;
501 for (
size_t i = 0; i < total; ++i) {
502 logits[i] = tanhf(logits[i] * inv_cap) * cap;
static uint16_t float_to_bf16(float f)
Persistent pthread thread pool for CK-Engine inference.
void ck_threadpool_parallel_for_n(ck_threadpool_t *pool, int active_threads, int begin, int end, int grain_size, ck_range_fn_t fn, void *args)
ck_threadpool_t * ck_threadpool_global(void)
void(* ck_range_fn_t)(int begin, int end, void *args)
int ck_threadpool_n_threads(const ck_threadpool_t *pool)
Quantization block structures for weight-only quantization.
#define CK_FP16_TO_FP32(x)
#define CK_FP32_TO_FP16(x)
void gemma4_per_layer_prepare_forward(float *per_layer_input, const float *hidden, const int32_t *token_ids, const void *per_layer_token_emb, const uint16_t *per_layer_model_proj, const float *per_layer_proj_norm, int tokens, int num_layers, int embed_dim, int per_layer_dim, int vocab_size, float eps)
#define CK_GEMMA4_MAX_EMBED_DIM
void rmsnorm_forward_llama_production(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
void gemm_nt_f32_llama_production_output_range(const float *A, const float *B, const float *bias, float *C, int M, int N, int K, int output_begin, int output_end)
static void ck_gemma4_dequant_q5_k_block(const ck_gemma4_block_q5_K *block, float *out)
static int ck_gemma4_embed_row_group(const ck_gemma4_embed_args_t *args, int token, int tokens)
static void ck_gemma4_prepare_parallel(int tokens, ck_range_fn_t fn, ck_gemma4_prepare_args_t *args)
static void ck_gemma4_embed_range(int begin, int end, void *opaque)
void gemma4_per_layer_embed_forward(float *hidden, const float *per_layer_input, const float *inp_gate, const float *proj, const float *post_norm, const float *out_scale, int tokens, int layer, int num_layers, int embed_dim, int per_layer_dim, float eps, const int *segment_lengths, int num_segments, int singleton_tail)
static void ck_gemma4_unpack_q5_k_scales(const uint8_t *scales, uint8_t *sc, uint8_t *m)
static float ck_bf16_to_f32(uint16_t v)
static float ck_gemma4_gelu(float x)
void assistant_layer_scale_forward(float *hidden, const float *scale, int tokens, int embed_dim)
static float ck_gemma4_bf16_dot(const uint16_t *x, const uint16_t *y, int n)
void gemma4_per_layer_prepare_bf16_forward(float *per_layer_input, const float *hidden, const int32_t *token_ids, const uint16_t *per_layer_token_emb, const uint16_t *per_layer_model_proj, const float *per_layer_proj_norm, int tokens, int num_layers, int embed_dim, int per_layer_dim, int vocab_size, float eps)
void gemma4_final_logit_softcap_forward(float *logits, int tokens, int vocab_size, float cap)
static void ck_gemma4_prepare_bf16_range(int begin, int end, void *opaque)
static void ck_gemma4_prepare_q5_range(int begin, int end, void *opaque)
static void ck_gemma4_rmsnorm_tmp(const float *x, const float *gamma, float *out, int n, float eps)
static uint8_t ck_gemma4_q5_k_value(const ck_gemma4_block_q5_K *block, int subblock, int i)