ISPC 1.32: AVX10.2, APX, and Zen 6 Targets
ISPC 1.32: AVX10.2, APX, and Zen 6 Targets
Writing SIMD by hand with intrinsics is slow, brittle, and hard to port across SSE, AVX2, AVX-512, and whatever comes next. Intel Implicit SPMD Program Compiler (ISPC) is a C-like language with a small set of extensions so you write one serial-looking program and the compiler maps a gang of program instances onto the CPU’s SIMD lanes. ISPC 1.32.0 (13 October 2026) is the release that brings full AVX10.2 and APX code generation for the Diamond Rapids and Nova Lake target families, plus an explicit --cpu=znver6 for AMD Zen 6. This chapter teaches the SPMD mental model, how those new targets relate to packing width (-x4 … -x64), and the OS-support traps around APX and AMX that the multi-target dispatcher will not catch for you.
Learning goals
By the end of this chapter you can:
- Explain SPMD in ISPC: one source program, many instances,
uniformvsvarying - Name what AVX10.2 and APX add for SPMD C on the
avx10.2dmrandavx10.2nvlfamilies - Choose
--target/--cpu=znver6and explain lane packing (-x16vs-x32) - Use
--opt=disable-apxwhen the OS may not manage APX state - Sketch a docs-faithful
export/foreachkernel and how it links to C
Thesis
ISPC’s job is a thin abstraction over SIMD: you keep a C-like syntax and a clear map from source to lanes, instead of writing _mm512_* by hand. Version 1.32 does not invent a new programming model — it unlocks new code-generation backends so the same SPMD kernels can compile for upcoming Intel AVX10.2/APX CPUs and for Zen 6’s native float16 path.
Mental model — SPMD, gangs, packing
In SPMD, you write what looks like a scalar loop body. At runtime (and in the generated code), a gang of program instances runs together, one per SIMD lane of the chosen target width.
| Qualifier | Meaning |
|---|---|
uniform |
One value shared by the whole gang (scalars, loop bounds, pointers you share) |
varying |
One value per program instance (the data that rides in vector registers) |
foreach |
Parallel iteration that assigns work across the gang |
Packing is how many instances fit in one gang for a given target name:
| Target family (ISPC 1.32) | Typical packing | Notes from release notes / user’s guide |
|---|---|---|
avx10.2dmr-xN |
N ∈ {4,8,16,32,64} | Diamond Rapids; AVX10.2 + APX; AMX-capable variants exist |
avx10.2nvl-xN |
N ∈ {4,8,16,32,64} | Nova Lake; AVX10.2 + APX; no AMX (unlike dmr) |
--cpu=znver6 |
maps to avx512icl-x16 |
AMD Zen 6; native float16 arithmetic |
Macro ISPC_TARGET_AVX10_2NVL is predefined on the Nova Lake family. Wider packing uses more lanes per gang; it is not automatically “faster” — it changes register pressure, masking, and how well your data layout fills the gang.
C host ISPC gang (e.g. avx10.2nvl-x16)
-------- --------------------------------
float *a, *b, *c; foreach (i = 0 ... n-1) {
call ispc_add(a,b,c,n); c[i] = a[i] + b[i]; // varying loads/stores
}
// 16 instances of that assignment in SIMD
What AVX10.2 and APX enable
From the ISPC 1.32.0 release notes (LLVM 23.1.2 backend):
- AVX10.2 — newer x86 vector ISA; ISPC emits it for the
avx10.2dmrandavx10.2nvltargets so SPMD kernels use the hardware’s current vector ops instead of falling back to older AVX-512 subsets. - APX (Advanced Performance Extensions) — extended GPRs and related sub-features (
egpr,ndd,push2pop2,ppx,ccmp,cf,nf,zu,jmpabs). Onavx10.2dmr/avx10.2nvl, APX is enabled by default. pdep32/pext32/pdep64/pext64— new stdlib helpers (uniform and varying) for parallel bit deposit/extract; BMI2 where available, specialized for constant masks (Morton codes, packing).
The trap: CPUID ≠ OS support
The multi-target runtime dispatcher selects avx10.2dmr, avx10.2nvl, and AMX-capable variants from CPUID only. It does not check whether the OS has enabled APX or AMX XSAVE state.
| Situation | What to do |
|---|---|
| Binary may run on an OS without APX | Compile with --opt=disable-apx (or a subset, e.g. --opt=disable-apx=egpr) |
--target=host on Nova Lake / Diamond Rapids without OS APX |
ISPC keeps the detected target but disables APX codegen |
AMX tiles (avx512spr, avx512gnr, avx10.2dmr) |
Your app must verify OS AMX permission before executing AMX; dispatcher does not |
Dispatch stubs themselves are always compiled without APX so the trampoline stays portable.
Worked example — SPMD add (docs-faithful)
ISPC is not installed on this writer machine; the listing below follows the official ISPC user’s guide / website SPMD model and 1.32 target naming. Treat output as illustrative until you compile locally.
// simple.ispc — gang of instances adds two float arrays
export void simple_add(uniform float a[], uniform float b[],
uniform float c[], uniform int count) {
foreach (i = 0 ... count) {
c[i] = a[i] + b[i];
}
}// main.c — call the export from ordinary C
#include <stdio.h>
#include <stdlib.h>
void simple_add(float a[], float b[], float c[], int count);
int main(void) {
const int n = 1024;
float *a = malloc(n * sizeof *a);
float *b = malloc(n * sizeof *b);
float *c = malloc(n * sizeof *c);
for (int i = 0; i < n; i++) {
a[i] = (float)i;
b[i] = 1.0f;
}
simple_add(a, b, c, n);
printf("c[0]=%.1f c[n-1]=%.1f\n", c[0], c[n - 1]);
free(a); free(b); free(c);
return 0;
}# Diamond Rapids / Nova Lake style targets (ISPC 1.32+)
ispc --target=avx10.2nvl-x16 simple.ispc -o simple.o
# or multi-target dispatch:
# ispc --target=avx2-i32x8,avx10.2nvl-x16,avx10.2dmr-x16 simple.ispc -o simple.o
# Zen 6 CPU tuning (maps to avx512icl-x16 + native float16)
ispc --cpu=znver6 --target=avx512icl-x16 simple.ispc -o simple.o
# Portable APX-off binary for mixed OS fleets
ispc --target=avx10.2nvl-x16 --opt=disable-apx simple.ispc -o simple.o
cc -O2 main.c simple.o -o simple_add
./simple_addExpected shape of output once built on a machine with ISPC 1.32:
c[0]=1.0 c[n-1]=1024.0
Case — picking packing width
| Goal | Prefer |
|---|---|
| Match AVX-512 512-bit float lanes | often -x16 for float |
| Experiment with double-pumped / wider gangs | -x32 / -x64 (more instances, more masking cost) |
| Ship one binary for many CPUs | multi-target list + runtime dispatcher; remember APX/AMX OS caveats |
The trap
- Treating dispatcher selection as “safe to run APX/AMX” — it is not; add an OS check or
--opt=disable-apx. - Confusing
avx10.2nvl(no AMX) withavx10.2dmr(AMX-capable family). - Assuming Zen 6 (
--cpu=znver6) is an AVX10.2 target — it maps toavx512icl-x16with nativefloat16, per the user’s guide. - Stripping symbols / skipping the C header ISPC generates for
exportand then wondering why the linker cannot find the kernel.
The boring rule
Write SPMD kernels with clear uniform / varying boundaries; pick --target for the ISA you need; for AVX10.2 fleets, decide APX on vs --opt=disable-apx as a deployment property, not an afterthought.
Try this
- Install ISPC 1.32 from ispc.github.io (no system package install required for this chapter’s verification path — use the official binary tarball).
- Run
ispc --support-matrixand locateavx10.2nvl,avx10.2dmr, andznver6. - Compile the add kernel once with
--opt=disable-apxand once without; compareobjdump -dfor APX-related encodings if you have a disassembler. - Read the “Updating ISPC Programs For Changes In ISPC 1.32.0” section of the user’s guide before upgrading multi-target builds.
Sources
- ISPC home: https://ispc.github.io/
- ISPC user’s guide: https://ispc.github.io/ispc.html
- Release notes (v1.32.0): https://raw.githubusercontent.com/ispc/ispc/main/docs/ReleaseNotes.txt
- GitHub releases: https://github.com/ispc/ispc/releases