Skip to content

cl_pocl_host_kernel: reduce launch overhead on x86 - #9

Open
maleadt wants to merge 2 commits into
tb/host-kernelfrom
tb/host-kernel-launch-cost
Open

maleadt wants to merge 2 commits into
tb/host-kernelfrom
tb/host-kernel-launch-cost

Conversation

@maleadt

@maleadt maleadt commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Stacked on #2 (cl_pocl_host_kernel). Two changes to clRunHostKernelPOCL reduce a trivial KernelAbstractions.jl launch on a Xeon E3-1245 v6 (Kaby Lake) from 566 to 498 cycles, measured with local builds:

  1. No division for ranges that start in the first row (566 → 518 cycles). Computing the first work-group's coordinates previously required two 64-bit divisions, each taking tens of cycles on Intel CPUs before Ice Lake. Launches on one thread always start at group 0.
  2. Skip the second MXCSR read when the caller's environment already matches the kernel's (518 → 498 cycles). This drops an STMXCSR and a store-forwarding stall.

Neither change is measurable on a Ryzen 5950X.

Contract change (2): the header now promises what a C function call does: the caller's floating-point control modes and previously raised exception flags are preserved, and which further flags the call raises is unspecified. On x86, when the caller's environment already matches the kernel's (round to nearest, exceptions masked, the kernel's FTZ setting, as in Julia by default), flags the kernel raises now stay raised. Previously, the caller's flags were always restored exactly. AArch64 still restores FPCR and FPSR. The test checks the contract (control modes and earlier flags survive, in both the matching and the differing case), not which flags leak.

Validation: runtime/test_cl_pocl_host_kernel passes with loopvec, cbs, and cpu_jit. The KernelAbstractions suite passes with both changes on the JLL series (tb/jll-series-release_next). On this branch's base, that suite stops in WorkitemLoops on a barrier kernel: main lacks the barrier fixes included in the JLLs (#4 and others).

…t row

clRunHostKernelPOCL used two 64-bit divisions to compute the range's first
work-group coordinates. Each takes tens of cycles on Intel CPUs before
Ice Lake. Ranges starting in the grid's first row, as launches on one thread
do, now need neither division. A trivial KernelAbstractions launch on a
Xeon E3-1245 v6 takes 518 instead of 566 cycles in a local build.
When the caller's floating-point environment already matches the kernel's,
the kernel can only raise further exception flags, as a function call would.
Leaving them avoids a second MXCSR read (STMXCSR) and a store-forwarding
stall: a trivial KernelAbstractions launch on a Xeon E3-1245 v6 takes 498
instead of 518 cycles in a local build.

The documented contract becomes the C function-call one on x86 and AArch64:
the caller's control modes and previously raised flags are preserved, and
which further flags the call raises is unspecified. AArch64 still restores
FPCR and FPSR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant