27 "HARD KERNEL CONTRACT FAULT: llama.cpp attention gate "
28 "requires expf from libm.so.6\n");
33#if defined(__GNUC__) || defined(__clang__)
48 const int packed_dim = q_dim + gate_dim;
49 if (!packed_qg || !q || !gate || rows <= 0 || q_dim <= 0 || gate_dim <= 0) {
55 const int q_groups = q_dim / group_dim;
56 const int gate_group_dim = (q_groups > 0 && gate_dim % q_groups == 0) ? (gate_dim / q_groups) : gate_dim;
57 for (
int row = 0; row < rows; ++row) {
58 const float *src = packed_qg + (size_t) row * (
size_t) packed_dim;
59 float *q_dst = q + (size_t) row * (
size_t) q_dim;
60 float *gate_dst = gate + (size_t) row * (
size_t) gate_dim;
61 if (q_groups > 0 && q_groups * group_dim == q_dim && q_groups * gate_group_dim == gate_dim) {
62 for (
int group = 0; group < q_groups; ++group) {
63 const size_t src_group_off = (size_t) group * (
size_t) (group_dim + gate_group_dim);
65 q_dst + (
size_t) group * (
size_t) group_dim,
67 (
size_t) group_dim *
sizeof(
float));
69 gate_dst + (
size_t) group * (
size_t) gate_group_dim,
70 src + src_group_off + (
size_t) group_dim,
71 (
size_t) gate_group_dim *
sizeof(
float));
74 memcpy(q_dst, src, (
size_t) q_dim *
sizeof(
float));
75 memcpy(gate_dst, src + q_dim, (
size_t) gate_dim *
sizeof(
float));
87 const int packed_dim = q_dim + gate_dim;
88 if (!d_q || !d_gate || !d_packed_qg || rows <= 0 || q_dim <= 0 || gate_dim <= 0) {
94 const int q_groups = q_dim / group_dim;
95 const int gate_group_dim = (q_groups > 0 && gate_dim % q_groups == 0) ? (gate_dim / q_groups) : gate_dim;
96 for (
int row = 0; row < rows; ++row) {
97 const float *dq_src = d_q + (size_t) row * (
size_t) q_dim;
98 const float *dg_src = d_gate + (size_t) row * (
size_t) gate_dim;
99 float *dst = d_packed_qg + (size_t) row * (
size_t) packed_dim;
100 if (q_groups > 0 && q_groups * group_dim == q_dim && q_groups * gate_group_dim == gate_dim) {
101 for (
int group = 0; group < q_groups; ++group) {
102 const size_t dst_group_off = (size_t) group * (
size_t) (group_dim + gate_group_dim);
105 dq_src + (
size_t) group * (
size_t) group_dim,
106 (
size_t) group_dim *
sizeof(
float));
108 dst + dst_group_off + (
size_t) group_dim,
109 dg_src + (
size_t) group * (
size_t) gate_group_dim,
110 (
size_t) gate_group_dim *
sizeof(
float));
113 memcpy(dst, dq_src, (
size_t) q_dim *
sizeof(
float));
114 memcpy(dst + q_dim, dg_src, (
size_t) gate_dim *
sizeof(
float));
124} ck_attn_gate_sigmoid_mul_args_t;
129 const ck_attn_gate_sigmoid_mul_args_t *args =
130 (
const ck_attn_gate_sigmoid_mul_args_t *)opaque;
131 for (
int row = begin; row <
end; ++row) {
133 args->x + (size_t)row * (
size_t)args->dim;
134 const float *gate_row =
135 args->gate + (size_t)row * (
size_t)args->dim;
137 args->out + (size_t)row * (
size_t)args->dim;
138 const int dim = args->dim;
139 for (
int col = 0; col < dim; ++col) {
148 const uintptr_t lhs_begin = (uintptr_t)lhs;
149 const uintptr_t rhs_begin = (uintptr_t)rhs;
150 const size_t bytes = elements *
sizeof(float);
151 return lhs_begin < rhs_begin + bytes && rhs_begin < lhs_begin + bytes;
160 if (!x || !gate || !out || rows <= 0 || num_heads <= 0 ||
161 state_dim <= 0 || num_heads > INT_MAX / state_dim) {
164 const int dim = num_heads * state_dim;
165 const size_t elements = (size_t)rows * (
size_t)dim;
166 ck_attn_gate_sigmoid_mul_args_t args = {x, gate, out, dim};
167 const size_t minimum_elements_per_thread = 32768u;
169 const int partial_x_overlap = out != x &&
172 if (partial_x_overlap || gate_overlap ||
173 elements < 2u * minimum_elements_per_thread) {
180 size_t useful_threads =
181 (elements + minimum_elements_per_thread - 1u) /
182 minimum_elements_per_thread;
183 if ((
size_t)active > useful_threads) {
184 active = (int)useful_threads;
192 pool, active, 0, rows, 4,
205 if (!x || !gate || !out || rows <= 0 || num_heads <= 0 || state_dim <= 0) {
208 const int dim = num_heads * state_dim;
209 for (
int row = 0; row < rows; ++row) {
210 const float *x_row = x + (size_t)row * (
size_t)dim;
211 const float *gate_row = gate + (size_t)row * (
size_t)dim;
212 float *out_row = out + (size_t)row * (
size_t)dim;
213 for (
int col = 0; col < dim; col += 16) {
214 const int width = dim - col < 16 ? dim - col : 16;
217 gate_row + col, sigmoid, 1, width);
218 for (
int lane = 0; lane < width; ++lane) {
222 x_bf16 * sigmoid_bf16));
234 const int dim = num_heads * state_dim;
235 for (
int row = 0; row < rows; ++row) {
236 const float *x_row = x + (size_t) row * (
size_t) dim;
237 const float *gate_row = gate + (size_t) row * (
size_t) num_heads;
238 float *out_row = out + (size_t) row * (
size_t) dim;
239 for (
int head = 0; head < num_heads; ++head) {
240 const float value = gate_row[head];
241 const float scale = value > 20.0f
243 : log1pf(expf(value));
244 const size_t base = (size_t) head * (
size_t) state_dim;
245 for (
int col = 0; col < state_dim; ++col) {
246 out_row[base + (size_t) col] =
247 x_row[base + (
size_t) col] * scale;
261 const int dim = num_heads * state_dim;
262 for (
int row = 0; row < rows; ++row) {
263 const float *d_out_row = d_out + (size_t) row * (
size_t) dim;
264 const float *x_row = x + (size_t) row * (
size_t) dim;
265 const float *gate_row = gate + (size_t) row * (
size_t) dim;
266 float *d_x_row = d_x + (size_t) row * (
size_t) dim;
267 float *d_gate_row = d_gate + (size_t) row * (
size_t) dim;
268 for (
int col = 0; col < dim; ++col) {
270 d_x_row[col] = d_out_row[col] * sig;
271 d_gate_row[col] = d_out_row[col] * x_row[col] * sig * (1.0f - sig);
static uint16_t float_to_bf16(float f)
static float bf16_to_float(uint16_t v)
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)
int ck_threadpool_thread_id(const ck_threadpool_t *pool)
int ck_threadpool_n_threads(const ck_threadpool_t *pool)
void recurrent_sigmoid_forward_pytorch_bf16_input_fp32_output(const float *x, float *out, int rows, int dim)
static void ck_bind_hybrid_llama_libm(void)
void split_q_gate_backward(const float *d_q, const float *d_gate, float *d_packed_qg, int rows, int q_dim, int gate_dim, int group_dim)
void attn_gate_sigmoid_mul_pytorch_bf16_storage(const float *x, const float *gate, float *out, int rows, int num_heads, int state_dim)
void attn_gate_sigmoid_mul_forward(const float *x, const float *gate, float *out, int rows, int num_heads, int state_dim)
void attn_gate_softplus_mul_forward(const float *x, const float *gate, float *out, int rows, int num_heads, int state_dim)
static void * ck_hybrid_libm_handle
static pthread_once_t ck_hybrid_libm_once
static int hybrid_ranges_overlap(const float *lhs, const float *rhs, size_t elements)
static ck_hybrid_libm_f32_fn ck_hybrid_llama_expf
static void attn_gate_sigmoid_mul_row_range(int begin, int end, void *opaque)
float(* ck_hybrid_libm_f32_fn)(float)
void attn_gate_sigmoid_mul_backward(const float *d_out, const float *x, const float *gate, float *d_x, float *d_gate, int rows, int num_heads, int state_dim)
static float hybrid_sigmoid(float x)
void split_q_gate_forward(const float *packed_qg, float *q, float *gate, int rows, int q_dim, int gate_dim, int group_dim)
__attribute__((visibility("default"))) CKTokenizer *ck_tokenizer_create(CKTokenizerType type)