← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
loss_kernels.c File Reference

Loss function kernels (cross-entropy, etc.) More...

#include "ckernel_engine.h"
#include <math.h>
#include <stdlib.h>

Go to the source code of this file.

Functions

static int ce_legacy_mode_enabled (void)
 
static int ce_targets_all_valid_no_ignore (const int32_t *targets, int tokens, int vocab_size)
 
static int parse_env_bool_on (const char *name)
 
void softmax_cross_entropy_loss (const float *logits, const int32_t *targets, int tokens, int vocab_size, float *d_logits, float *loss_out)
 
static void softmax_cross_entropy_loss_index_mean_impl (const float *logits, const int32_t *targets, int tokens, int vocab_size, float *d_logits, float *loss_out, int force_strict_math)
 
static void softmax_cross_entropy_loss_legacy_mean_impl (const float *logits, const int32_t *targets, int tokens, int vocab_size, float *d_logits, float *loss_out)
 
void softmax_cross_entropy_loss_ptref (const float *logits, const int32_t *targets, int tokens, int vocab_size, float *d_logits, float *loss_out)
 
static void zero_row_f32 (float *row, int cols)
 

Detailed Description

Loss function kernels (cross-entropy, etc.)

CK-ENGINE KERNEL RULES:

  1. NO malloc/free - memory via bump allocator, pointers passed in
  2. NO OpenMP - parallelization at orchestrator/codegen layer
  3. API must define: inputs, outputs, workspace, and memory layouts
  4. Pure computation - deterministic, no side effects

After changes: make test && make llamacpp-parity-full

Cross-entropy: L = -log(softmax(logits)[target])

Definition in file loss_kernels.c.

Function Documentation

◆ ce_legacy_mode_enabled()

static int ce_legacy_mode_enabled ( void  )
static

Definition at line 46 of file loss_kernels.c.

47{
48 static int cached = -1;
49 if (cached < 0) {
50 cached = parse_env_bool_on("CK_CE_LEGACY_MODE") ? 1 : 0;
51 }
52 return cached;
53}
static int parse_env_bool_on(const char *name)

References parse_env_bool_on().

Referenced by softmax_cross_entropy_loss().

◆ ce_targets_all_valid_no_ignore()

static int ce_targets_all_valid_no_ignore ( const int32_t *  targets,
int  tokens,
int  vocab_size 
)
static

Definition at line 248 of file loss_kernels.c.

249{
250 for (int t = 0; t < tokens; ++t) {
251 const int target = targets[t];
252 if (target < 0 || target >= vocab_size) {
253 return 0;
254 }
255 }
256 return 1;
257}
int vocab_size
Definition true_bpe.h:193

References vocab_size.

Referenced by softmax_cross_entropy_loss().

◆ parse_env_bool_on()

static int parse_env_bool_on ( const char *  name)
static

Definition at line 29 of file loss_kernels.c.

30{
31 const char *v = getenv(name);
32 if (!v || !v[0]) {
33 return 0;
34 }
35 if (v[0] == '1' || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T') {
36 return 1;
37 }
38 return 0;
39}

Referenced by ce_legacy_mode_enabled().

◆ softmax_cross_entropy_loss()

void softmax_cross_entropy_loss ( const float *  logits,
const int32_t *  targets,
int  tokens,
int  vocab_size,
float *  d_logits,
float *  loss_out 
)

Definition at line 259 of file loss_kernels.c.

265{
266 if (!logits || !targets || !d_logits || tokens <= 0 || vocab_size <= 0) {
267 if (loss_out) {
268 *loss_out = 0.0f;
269 }
270 return;
271 }
272
275 logits, targets, tokens, vocab_size, d_logits, loss_out);
276 return;
277 }
278
280 logits, targets, tokens, vocab_size, d_logits, loss_out, -1);
281}
static int ce_targets_all_valid_no_ignore(const int32_t *targets, int tokens, int vocab_size)
static int ce_legacy_mode_enabled(void)
static void softmax_cross_entropy_loss_index_mean_impl(const float *logits, const int32_t *targets, int tokens, int vocab_size, float *d_logits, float *loss_out, int force_strict_math)
static void softmax_cross_entropy_loss_legacy_mean_impl(const float *logits, const int32_t *targets, int tokens, int vocab_size, float *d_logits, float *loss_out)

References ce_legacy_mode_enabled(), ce_targets_all_valid_no_ignore(), softmax_cross_entropy_loss_index_mean_impl(), softmax_cross_entropy_loss_legacy_mean_impl(), and vocab_size.

Referenced by softmax_cross_entropy_loss_bf16().

◆ softmax_cross_entropy_loss_index_mean_impl()

static void softmax_cross_entropy_loss_index_mean_impl ( const float *  logits,
const int32_t *  targets,
int  tokens,
int  vocab_size,
float *  d_logits,
float *  loss_out,
int  force_strict_math 
)
static

Definition at line 64 of file loss_kernels.c.

71{
72 if (!logits || !targets || !d_logits || tokens <= 0 || vocab_size <= 0) {
73 if (loss_out) {
74 *loss_out = 0.0f;
75 }
76 return;
77 }
78
79 const int ignore_index = -100;
80 const int strict = (force_strict_math >= 0) ? (force_strict_math ? 1 : 0)
82 double total_loss = 0.0;
83 int valid_tokens = 0;
84 int invalid_target_seen = 0;
85
86 for (int t = 0; t < tokens; ++t) {
87 const float *row = logits + (size_t)t * (size_t)vocab_size;
88 float *drow = d_logits + (size_t)t * (size_t)vocab_size;
89 const int target = targets[t];
90
91 if (target == ignore_index) {
93 continue;
94 }
95 if (target < 0 || target >= vocab_size) {
97 invalid_target_seen = 1;
98 continue;
99 }
100
101 if (strict) {
102 double max_logit = (double)row[0];
103 for (int v = 1; v < vocab_size; ++v) {
104 const double rv = (double)row[v];
105 if (rv > max_logit) {
106 max_logit = rv;
107 }
108 }
109
110 double sum_exp = 0.0;
111 for (int v = 0; v < vocab_size; ++v) {
112 sum_exp += exp((double)row[v] - max_logit);
113 }
114 const double inv_sum = 1.0 / sum_exp;
115 for (int v = 0; v < vocab_size; ++v) {
116 drow[v] = (float)(exp((double)row[v] - max_logit) * inv_sum);
117 }
118
119 total_loss += -(double)row[target] + max_logit + log(sum_exp);
120 } else {
121 float max_logit = row[0];
122 for (int v = 1; v < vocab_size; ++v) {
123 if (row[v] > max_logit) {
124 max_logit = row[v];
125 }
126 }
127
128 double sum_exp = 0.0;
129 for (int v = 0; v < vocab_size; ++v) {
130 const float e = expf(row[v] - max_logit);
131 drow[v] = e;
132 sum_exp += (double)e;
133 }
134 const float inv_sum = 1.0f / (float)sum_exp;
135 for (int v = 0; v < vocab_size; ++v) {
136 drow[v] *= inv_sum;
137 }
138
139 total_loss += -(double)row[target] + (double)max_logit + log(sum_exp);
140 }
141
142 drow[target] -= 1.0f;
143 ++valid_tokens;
144 }
145
146 if (valid_tokens > 0) {
147 const float scale = 1.0f / (float)valid_tokens;
148 for (int t = 0; t < tokens; ++t) {
149 float *drow = d_logits + (size_t)t * (size_t)vocab_size;
150 for (int v = 0; v < vocab_size; ++v) {
151 drow[v] *= scale;
152 }
153 }
154 }
155
156 if (loss_out) {
157 if (invalid_target_seen || valid_tokens == 0) {
158 *loss_out = NAN;
159 } else {
160 *loss_out = (float)(total_loss / (double)valid_tokens);
161 }
162 }
163}
int ck_strict_parity_enabled(void)
static void zero_row_f32(float *row, int cols)

References ck_strict_parity_enabled(), vocab_size, and zero_row_f32().

Referenced by softmax_cross_entropy_loss(), and softmax_cross_entropy_loss_ptref().

◆ softmax_cross_entropy_loss_legacy_mean_impl()

static void softmax_cross_entropy_loss_legacy_mean_impl ( const float *  logits,
const int32_t *  targets,
int  tokens,
int  vocab_size,
float *  d_logits,
float *  loss_out 
)
static

Definition at line 169 of file loss_kernels.c.

175{
176 const int strict = ck_strict_parity_enabled();
177 const double scale = 1.0 / (double)tokens;
178 double total_loss = 0.0;
179
180 for (int t = 0; t < tokens; ++t) {
181 const float *row = logits + (size_t)t * (size_t)vocab_size;
182 float *drow = d_logits + (size_t)t * (size_t)vocab_size;
183 const int target = targets[t];
184
185 if (strict) {
186 double max_logit = (double)row[0];
187 for (int v = 1; v < vocab_size; ++v) {
188 const double rv = (double)row[v];
189 if (rv > max_logit) {
190 max_logit = rv;
191 }
192 }
193
194 double sum_exp = 0.0;
195 for (int v = 0; v < vocab_size; ++v) {
196 sum_exp += exp((double)row[v] - max_logit);
197 }
198 const double inv_sum = 1.0 / sum_exp;
199 for (int v = 0; v < vocab_size; ++v) {
200 const double p = exp((double)row[v] - max_logit) * inv_sum;
201 drow[v] = (float)(p * scale);
202 }
203
204 if (target >= 0 && target < vocab_size) {
205 const double log_sum_exp = log(sum_exp);
206 const double target_logit = (double)row[target];
207 total_loss += -(target_logit - max_logit - log_sum_exp);
208 drow[target] -= (float)scale;
209 }
210 } else {
211 float max_logit = row[0];
212 for (int v = 1; v < vocab_size; ++v) {
213 if (row[v] > max_logit) {
214 max_logit = row[v];
215 }
216 }
217
218 double sum_exp = 0.0;
219 for (int v = 0; v < vocab_size; ++v) {
220 const float e = expf(row[v] - max_logit);
221 drow[v] = e;
222 sum_exp += (double)e;
223 }
224
225 const float inv_sum = 1.0f / (float)sum_exp;
226 for (int v = 0; v < vocab_size; ++v) {
227 drow[v] *= inv_sum;
228 }
229
230 if (target >= 0 && target < vocab_size) {
231 const double log_sum_exp = log(sum_exp);
232 const double target_logit = (double)row[target];
233 total_loss += -(target_logit - (double)max_logit - log_sum_exp);
234 drow[target] -= 1.0f;
235 }
236
237 for (int v = 0; v < vocab_size; ++v) {
238 drow[v] *= (float)scale;
239 }
240 }
241 }
242
243 if (loss_out) {
244 *loss_out = (float)(total_loss / (double)tokens);
245 }
246}

References ck_strict_parity_enabled(), and vocab_size.

Referenced by softmax_cross_entropy_loss().

◆ softmax_cross_entropy_loss_ptref()

void softmax_cross_entropy_loss_ptref ( const float *  logits,
const int32_t *  targets,
int  tokens,
int  vocab_size,
float *  d_logits,
float *  loss_out 
)

Definition at line 292 of file loss_kernels.c.

298{
299 /*
300 * Keep a strict reference variant for parity experiments:
301 * - always uses strict math path,
302 * - same reduction / ignore semantics as default kernel.
303 */
305 logits, targets, tokens, vocab_size, d_logits, loss_out, 1);
306}

References softmax_cross_entropy_loss_index_mean_impl(), and vocab_size.

◆ zero_row_f32()

static void zero_row_f32 ( float *  row,
int  cols 
)
static

Definition at line 22 of file loss_kernels.c.

23{
24 for (int i = 0; i < cols; ++i) {
25 row[i] = 0.0f;
26 }
27}

Referenced by softmax_cross_entropy_loss_index_mean_impl().