Skip to content

Commit 980eabc

Browse files
committed
feat(core): vectorize SIMD-style tape operations for AD, IA, and McCormick Array evaluate speedup
1 parent 649e68a commit 980eabc

2 files changed

Lines changed: 74 additions & 1 deletion

File tree

packages/core/src/compiler/modelica/ad-codegen.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,14 @@ export class StaticTapeBuilder {
534534
// Reverse topological traversal
535535
for (let i = this.ops.length - 1; i >= 0; i--) {
536536
const op = this.ops[i]!; // eslint-disable-line @typescript-eslint/no-non-null-assertion
537-
if (op.type === "const" || op.type === "var") continue;
537+
if (
538+
op.type === "const" ||
539+
op.type === "var" ||
540+
op.type === "vec_var" ||
541+
op.type === "vec_const" ||
542+
op.type === "nop"
543+
)
544+
continue;
538545

539546
// Optimization: if dt is 0, skip branching
540547
lines.push(` if (dt[${i}] != 0.0) {`);
@@ -580,6 +587,29 @@ export class StaticTapeBuilder {
580587
case "sqrt":
581588
lines.push(` dt[${op.a}] += dt[${i}] / (2.0 * t[${i}]);`);
582589
break;
590+
// ── Vector ops ──
591+
case "vec_add":
592+
lines.push(` for (int _k = 0; _k < ${op.size}; _k++) {`);
593+
lines.push(` dt[${op.a}+_k] += dt[${i}+_k]; dt[${op.b}+_k] += dt[${i}+_k];`);
594+
lines.push(` }`);
595+
break;
596+
case "vec_sub":
597+
lines.push(` for (int _k = 0; _k < ${op.size}; _k++) {`);
598+
lines.push(` dt[${op.a}+_k] += dt[${i}+_k]; dt[${op.b}+_k] -= dt[${i}+_k];`);
599+
lines.push(` }`);
600+
break;
601+
case "vec_mul":
602+
lines.push(` for (int _k = 0; _k < ${op.size}; _k++) {`);
603+
lines.push(` dt[${op.a}+_k] += dt[${i}+_k] * t[${op.b}+_k];`);
604+
lines.push(` dt[${op.b}+_k] += dt[${i}+_k] * t[${op.a}+_k];`);
605+
lines.push(` }`);
606+
break;
607+
case "vec_neg":
608+
lines.push(` for (int _k = 0; _k < ${op.size}; _k++) dt[${op.a}+_k] -= dt[${i}+_k];`);
609+
break;
610+
case "vec_subscript":
611+
lines.push(` dt[${op.a + op.offset}] += dt[${i}];`);
612+
break;
583613
}
584614
lines.push(` }`);
585615
}
@@ -592,6 +622,10 @@ export class StaticTapeBuilder {
592622
// Variables can be read multiple times (e.g. x in x + x).
593623
// Since `cache` deduplicates, there is only one `var: x` operator!
594624
gradients.set(op.name, i);
625+
} else if (op.type === "vec_var") {
626+
for (let k = 0; k < op.size; k++) {
627+
gradients.set(`${op.baseName}[${k + 1}]`, i + k);
628+
}
595629
}
596630
}
597631

packages/core/src/compiler/modelica/interval.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,45 @@ export function emitIntervalForwardC(
416416
case "sqrt":
417417
lines.push(`t_lo[${i}] = sqrt(fmax(0.0,t_lo[${op.a}])); t_hi[${i}] = sqrt(fmax(0.0,t_hi[${op.a}]));`);
418418
break;
419+
// ── Vector ops ──
420+
case "vec_var":
421+
for (let k = 0; k < op.size; k++) {
422+
const vr = varResolver(`${op.baseName}[${k + 1}]`);
423+
lines.push(`t_lo[${i + k}] = ${vr.lo}; t_hi[${i + k}] = ${vr.hi};`);
424+
}
425+
break;
426+
case "vec_const":
427+
for (let k = 0; k < op.size; k++) {
428+
lines.push(`t_lo[${i + k}] = ${formatNum(op.vals[k] ?? 0)}; t_hi[${i + k}] = ${formatNum(op.vals[k] ?? 0)};`);
429+
}
430+
break;
431+
case "vec_add":
432+
lines.push(
433+
`for (int _k = 0; _k < ${op.size}; _k++) { t_lo[${i}+_k] = t_lo[${op.a}+_k] + t_lo[${op.b}+_k]; t_hi[${i}+_k] = t_hi[${op.a}+_k] + t_hi[${op.b}+_k]; }`,
434+
);
435+
break;
436+
case "vec_sub":
437+
lines.push(
438+
`for (int _k = 0; _k < ${op.size}; _k++) { t_lo[${i}+_k] = t_lo[${op.a}+_k] - t_hi[${op.b}+_k]; t_hi[${i}+_k] = t_hi[${op.a}+_k] - t_lo[${op.b}+_k]; }`,
439+
);
440+
break;
441+
case "vec_mul":
442+
lines.push(`for (int _k = 0; _k < ${op.size}; _k++) {`);
443+
lines.push(` double p1=t_lo[${op.a}+_k]*t_lo[${op.b}+_k], p2=t_lo[${op.a}+_k]*t_hi[${op.b}+_k],`);
444+
lines.push(` p3=t_hi[${op.a}+_k]*t_lo[${op.b}+_k], p4=t_hi[${op.a}+_k]*t_hi[${op.b}+_k];`);
445+
lines.push(` t_lo[${i}+_k] = fmin(fmin(p1,p2),fmin(p3,p4)); t_hi[${i}+_k] = fmax(fmax(p1,p2),fmax(p3,p4));`);
446+
lines.push(`}`);
447+
break;
448+
case "vec_neg":
449+
lines.push(
450+
`for (int _k = 0; _k < ${op.size}; _k++) { t_lo[${i}+_k] = -t_hi[${op.a}+_k]; t_hi[${i}+_k] = -t_lo[${op.a}+_k]; }`,
451+
);
452+
break;
453+
case "vec_subscript":
454+
lines.push(`t_lo[${i}] = t_lo[${op.a + op.offset}]; t_hi[${i}] = t_hi[${op.a + op.offset}];`);
455+
break;
456+
case "nop":
457+
break;
419458
}
420459
}
421460
return lines;

0 commit comments

Comments
 (0)