fix(HIGH-05): ane_eval() returns bool, add step_ok tracking

- stories_io.h: ane_eval() changed from void to bool; captures BOOL
  return from evaluateWithQoS:options:request:error: with NSError log
- train_large.m: step_ok tracks all 6 ane_eval() results per step;
  gradient update skipped if any ANE eval fails in that step

ref: docs/reports/security-audit-2026-03-02.md HIGH-05

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
manni07 2026-03-02 23:35:48 +01:00
parent 42eae54975
commit f78b9439dd
2 changed files with 181 additions and 172 deletions

View File

@ -161,7 +161,11 @@ static void free_kern(Kern *k) {
CFRelease(k->model); CFRelease(k->request); CFRelease(k->tmpDir); CFRelease(k->model); CFRelease(k->request); CFRelease(k->tmpDir);
free(k); free(k);
} }
static void ane_eval(Kern *k) { static bool ane_eval(Kern *k) { // HIGH-05: was void
id mdl = (__bridge id)k->model; id req = (__bridge id)k->request; NSError *e = nil; id mdl = (__bridge id)k->model; id req = (__bridge id)k->request; NSError *e = nil;
((BOOL(*)(id,SEL,unsigned int,id,id,NSError**))objc_msgSend)(mdl, @selector(evaluateWithQoS:options:request:error:), 21, @{}, req, &e); BOOL ok = ((BOOL(*)(id,SEL,unsigned int,id,id,NSError**))objc_msgSend)(
mdl, @selector(evaluateWithQoS:options:request:error:), 21, @{}, req, &e);
if (!ok) fprintf(stderr, " [ane_eval] FAILED: %s\n",
e ? [[e description] UTF8String] : "unknown error");
return (bool)ok;
} }

View File

@ -408,6 +408,7 @@ int main(int argc, char *argv[]) {
uint64_t tt = mach_absolute_time(); uint64_t tt = mach_absolute_time();
double t_ane=0,t_io=0,t_elem=0,t_rms=0,t_cblas_wait=0,t_cls=0; double t_ane=0,t_io=0,t_elem=0,t_rms=0,t_cblas_wait=0,t_cls=0;
bool step_ok = true; // HIGH-05: track ANE eval success across all acc steps
for (int a=0; a<ACCUM_STEPS && step<total_steps; a++, step++) { for (int a=0; a<ACCUM_STEPS && step<total_steps; a++, step++) {
uint64_t t0,t1; uint64_t t0,t1;
// Sample random position in token data // Sample random position in token data
@ -433,7 +434,7 @@ int main(int argc, char *argv[]) {
t1=mach_absolute_time(); t_cblas_wait+=tb_ms(t1-t0); t0=t1; t1=mach_absolute_time(); t_cblas_wait+=tb_ms(t1-t0); t0=t1;
io_write_fp16(kern[L].fwdAttn->ioIn, x_cur, DIM, SEQ); io_write_fp16(kern[L].fwdAttn->ioIn, x_cur, DIM, SEQ);
t1=mach_absolute_time(); t_io+=tb_ms(t1-t0); t0=t1; t1=mach_absolute_time(); t_io+=tb_ms(t1-t0); t0=t1;
ane_eval(kern[L].fwdAttn); step_ok &= ane_eval(kern[L].fwdAttn);
t1=mach_absolute_time(); t_ane+=tb_ms(t1-t0); t0=t1; t1=mach_absolute_time(); t_ane+=tb_ms(t1-t0); t0=t1;
io_read_fp16(kern[L].fwdAttn->ioOut, ac->o_out, 0, DIM, SEQ); io_read_fp16(kern[L].fwdAttn->ioOut, ac->o_out, 0, DIM, SEQ);
io_read_fp16(kern[L].fwdAttn->ioOut, ac->attn_out, 4*DIM, DIM, SEQ); io_read_fp16(kern[L].fwdAttn->ioOut, ac->attn_out, 4*DIM, DIM, SEQ);
@ -446,7 +447,7 @@ int main(int argc, char *argv[]) {
// FFN forward // FFN forward
io_write_fp16(kern[L].fwdFFN->ioIn, ac->x2, DIM, SEQ); io_write_fp16(kern[L].fwdFFN->ioIn, ac->x2, DIM, SEQ);
t1=mach_absolute_time(); t_io+=tb_ms(t1-t0); t0=t1; t1=mach_absolute_time(); t_io+=tb_ms(t1-t0); t0=t1;
ane_eval(kern[L].fwdFFN); step_ok &= ane_eval(kern[L].fwdFFN);
t1=mach_absolute_time(); t_ane+=tb_ms(t1-t0); t0=t1; t1=mach_absolute_time(); t_ane+=tb_ms(t1-t0); t0=t1;
io_read_fp16(kern[L].fwdFFN->ioOut, ac->ffn_out, 0, DIM, SEQ); io_read_fp16(kern[L].fwdFFN->ioOut, ac->ffn_out, 0, DIM, SEQ);
io_read_fp16(kern[L].fwdFFN->ioOut, ac->h1, DIM, HIDDEN, SEQ); io_read_fp16(kern[L].fwdFFN->ioOut, ac->h1, DIM, HIDDEN, SEQ);
@ -509,7 +510,7 @@ int main(int argc, char *argv[]) {
// FFN backward (ANE) // FFN backward (ANE)
io_write_fp16_at(kern[L].ffnBwd->ioIn, 0, dffn, DIM, SEQ); io_write_fp16_at(kern[L].ffnBwd->ioIn, 0, dffn, DIM, SEQ);
io_copy(kern[L].ffnBwd->ioIn, DIM, kern[L].fwdFFN->ioOut, DIM, 2*HIDDEN, SEQ); io_copy(kern[L].ffnBwd->ioIn, DIM, kern[L].fwdFFN->ioOut, DIM, 2*HIDDEN, SEQ);
ane_eval(kern[L].ffnBwd); step_ok &= ane_eval(kern[L].ffnBwd);
io_read_fp16(kern[L].ffnBwd->ioOut, dx_ffn, 0, DIM, SEQ); io_read_fp16(kern[L].ffnBwd->ioOut, dx_ffn, 0, DIM, SEQ);
io_read_fp16(kern[L].ffnBwd->ioOut, dh1, DIM, HIDDEN, SEQ); io_read_fp16(kern[L].ffnBwd->ioOut, dh1, DIM, HIDDEN, SEQ);
io_read_fp16(kern[L].ffnBwd->ioOut, dh3, DIM+HIDDEN, HIDDEN, SEQ); io_read_fp16(kern[L].ffnBwd->ioOut, dh3, DIM+HIDDEN, HIDDEN, SEQ);
@ -549,10 +550,10 @@ int main(int argc, char *argv[]) {
// SDPA backward (ANE) // SDPA backward (ANE)
io_copy(kern[L].sdpaBwd1->ioIn, 0, kern[L].fwdAttn->ioOut, DIM, 3*DIM, SEQ); io_copy(kern[L].sdpaBwd1->ioIn, 0, kern[L].fwdAttn->ioOut, DIM, 3*DIM, SEQ);
io_write_fp16_at(kern[L].sdpaBwd1->ioIn, 3*DIM, dx2, DIM, SEQ); io_write_fp16_at(kern[L].sdpaBwd1->ioIn, 3*DIM, dx2, DIM, SEQ);
ane_eval(kern[L].sdpaBwd1); step_ok &= ane_eval(kern[L].sdpaBwd1);
io_copy(sdpaBwd2[L]->ioIn, 0, kern[L].sdpaBwd1->ioOut, DIM, 2*SCORE_CH, SEQ); io_copy(sdpaBwd2[L]->ioIn, 0, kern[L].sdpaBwd1->ioOut, DIM, 2*SCORE_CH, SEQ);
io_copy(sdpaBwd2[L]->ioIn, 2*SCORE_CH, kern[L].fwdAttn->ioOut, DIM, 2*DIM, SEQ); io_copy(sdpaBwd2[L]->ioIn, 2*SCORE_CH, kern[L].fwdAttn->ioOut, DIM, 2*DIM, SEQ);
ane_eval(sdpaBwd2[L]); step_ok &= ane_eval(sdpaBwd2[L]);
io_read_fp16(sdpaBwd2[L]->ioOut, dq, 0, DIM, SEQ); io_read_fp16(sdpaBwd2[L]->ioOut, dq, 0, DIM, SEQ);
io_read_fp16(sdpaBwd2[L]->ioOut, dk, DIM, DIM, SEQ); io_read_fp16(sdpaBwd2[L]->ioOut, dk, DIM, DIM, SEQ);
@ -576,7 +577,7 @@ int main(int argc, char *argv[]) {
// QKV backward (ANE) // QKV backward (ANE)
io_copy(kern[L].qkvBwd->ioIn, 0, sdpaBwd2[L]->ioOut, 0, 2*DIM, SEQ); io_copy(kern[L].qkvBwd->ioIn, 0, sdpaBwd2[L]->ioOut, 0, 2*DIM, SEQ);
io_copy(kern[L].qkvBwd->ioIn, 2*DIM, kern[L].sdpaBwd1->ioOut, 0, DIM, SEQ); io_copy(kern[L].qkvBwd->ioIn, 2*DIM, kern[L].sdpaBwd1->ioOut, 0, DIM, SEQ);
ane_eval(kern[L].qkvBwd); step_ok &= ane_eval(kern[L].qkvBwd);
io_read_fp16(kern[L].qkvBwd->ioOut, dx_attn, 0, DIM, SEQ); io_read_fp16(kern[L].qkvBwd->ioOut, dx_attn, 0, DIM, SEQ);
// RMSNorm1 backward (using saved layer input) // RMSNorm1 backward (using saved layer input)
@ -632,6 +633,10 @@ int main(int argc, char *argv[]) {
"\"compiles\":%d}\n", "\"compiles\":%d}\n",
step, loss, step_ane, step_io, step_cls, step_elem, step_rms, step_cbw, g_compile_count); step, loss, step_ane, step_io, step_cls, step_elem, step_rms, step_cbw, g_compile_count);
} }
if (!step_ok) { // HIGH-05: skip gradient update if any ANE eval failed
fprintf(stderr, " Step %d: ANE eval error — gradient update skipped\n", step);
continue; // skip to next iteration of outer while (step < total_steps)
}
double tms = tb_ms(mach_absolute_time() - tt); double tms = tb_ms(mach_absolute_time() - tt);
total_train_ms += tms; total_train_ms += tms;
total_steps_done += steps_batch; total_steps_done += steps_batch;