diff --git a/kernel-builder/src/pyproject/deps.rs b/kernel-builder/src/pyproject/deps.rs index 065651b4c..4707f695c 100644 --- a/kernel-builder/src/pyproject/deps.rs +++ b/kernel-builder/src/pyproject/deps.rs @@ -93,9 +93,28 @@ pub fn render_deps(env: &Environment, build: &Build, write: &mut impl Write) -> .wrap_err("Cannot render CUTLASS dependency template")?; } Dependency::SyclTla => { + // An Xe35-only TU puts MXFP code that ocloc rejects elsewhere into the + // generic image, so that image can only lower to cri and pvc/bmg need + // alias targets. Otherwise one image serves all three, halving the + // device compilations per TU. + let cri_isolated_image = build.kernels.values().any(|kernel| { + kernel.sycl_flags().is_some_and(|flags| { + flags + .iter() + .any(|flag| flag.contains("__SYCL_TARGET_INTEL_GPU_CRI__")) + }) + }); + let (sycl_aot_devices, sycl_offload_targets) = if cri_isolated_image { + ("cri", "intel_gpu_pvc,intel_gpu_bmg_g21,spir64_gen,spir64") + } else { + ("pvc,bmg-g21,cri", "spir64_gen,spir64") + }; env.get_template("xpu/dep-sycl-tla.cmake") .wrap_err("Cannot get SYCL TLA dependency template")? - .render_captured_to(context! {}, &mut *write) + .render_captured_to( + context! { sycl_aot_devices, sycl_offload_targets }, + &mut *write, + ) .wrap_err("Cannot render SYCL TLA dependency template")?; } Dependency::MetalCpp => { diff --git a/kernel-builder/src/pyproject/templates/torch/preamble.cmake b/kernel-builder/src/pyproject/templates/torch/preamble.cmake index 380e8c7c9..09857fc6e 100644 --- a/kernel-builder/src/pyproject/templates/torch/preamble.cmake +++ b/kernel-builder/src/pyproject/templates/torch/preamble.cmake @@ -205,10 +205,55 @@ elseif(GPU_LANG STREQUAL "SYCL") endif() + # --- SYCL fat-binary flags ------------------------------------------------ + # One .so carries an AOT image per GPU in SYCL_AOT_DEVICES plus a spir64 JIT + # fallback; the runtime picks the matching image at load time. + # These variables are the single source of truth: a dependency may change them + # and call xpu_compose_sycl_flags() again to rebuild the flags. + set(SYCL_OFFLOAD_TARGETS "spir64_gen,spir64") + set(SYCL_AOT_DEVICES "pvc,xe-lpg,ats-m150") + set(SYCL_AOT_BACKEND_OPTIONS " -cl-intel-enable-auto-large-GRF-mode -cl-poison-unsupported-fp64-kernels -cl-intel-greater-than-4GB-buffer-required") + set(SYCL_SPIRV_EXT "") + + # Rebuild sycl_flags (compile) and sycl_link_flags (link) from the variables + # above. A macro so it runs in the including scope and can be re-invoked. + # # -foffload-fp32-prec-* keeps fp32 division and sqrt IEEE correctly rounded, # matching PyTorch; both the compile and the link step need them. - set(sycl_link_flags "-Wl,-z,noexecstack;-fsycl;--offload-compress;-foffload-fp32-prec-div;-foffload-fp32-prec-sqrt;-fsycl-targets=spir64_gen,spir64;-Xs;-device pvc,xe-lpg,ats-m150 -options ' -cl-intel-enable-auto-large-GRF-mode -cl-poison-unsupported-fp64-kernels -cl-intel-greater-than-4GB-buffer-required';") - set(sycl_flags "-fPIC;-fsycl;-fhonor-nans;-fhonor-infinities;-fno-associative-math;-fno-approx-func;-foffload-fp32-prec-div;-foffload-fp32-prec-sqrt;-fno-sycl-instrument-device-code;--offload-compress;-fsycl-targets=spir64_gen,spir64;") + macro(xpu_compose_sycl_flags) + set(sycl_flags + "-fPIC;-fsycl;-fhonor-nans;-fhonor-infinities;-fno-associative-math;-fno-approx-func;-foffload-fp32-prec-div;-foffload-fp32-prec-sqrt;-fno-sycl-instrument-device-code;--offload-compress;-fsycl-targets=${SYCL_OFFLOAD_TARGETS}") + + set(sycl_link_flags + "-Wl,-z,noexecstack;-fsycl;--offload-compress;-foffload-fp32-prec-div;-foffload-fp32-prec-sqrt;-fsycl-targets=${SYCL_OFFLOAD_TARGETS}") + + # Backend options reach one target each: spir64_gen takes -device, the + # intel_gpu_* aliases imply theirs. SHELL: stops CMake from deduplicating + # the identical -options and silently dropping all but the first target. + string(REPLACE "," ";" _sycl_aot_targets "${SYCL_OFFLOAD_TARGETS}") + foreach(_tgt IN LISTS _sycl_aot_targets) + if(_tgt STREQUAL "spir64_gen") + string(APPEND sycl_link_flags + ";SHELL:-Xsycl-target-backend=spir64_gen \"-device ${SYCL_AOT_DEVICES} -options '${SYCL_AOT_BACKEND_OPTIONS}'\"") + elseif(_tgt MATCHES "^intel_gpu_") + string(APPEND sycl_link_flags + ";SHELL:-Xsycl-target-backend=${_tgt} \"-options '${SYCL_AOT_BACKEND_OPTIONS}'\"") + endif() + endforeach() + + # SYCL_SPIRV_EXT must be a COMPLETE list (translator replaces, not merges). + # A custom -spirv-ext only reaches an image whose triple matches the exact + # fsycl-targets alias, so emit one -Xspirv-translator= per target. + if(SYCL_SPIRV_EXT) + string(REPLACE "," ";" _sycl_ext_targets "${SYCL_OFFLOAD_TARGETS}") + foreach(_tgt IN LISTS _sycl_ext_targets) + string(APPEND sycl_link_flags + ";SHELL:-Xspirv-translator=${_tgt} -spirv-ext=${SYCL_SPIRV_EXT}") + endforeach() + endif() + endmacro() + + xpu_compose_sycl_flags() set(GPU_FLAGS "${sycl_flags}") diff --git a/kernel-builder/src/pyproject/templates/tvm_ffi/preamble.cmake b/kernel-builder/src/pyproject/templates/tvm_ffi/preamble.cmake index abee3b252..ce48feb79 100644 --- a/kernel-builder/src/pyproject/templates/tvm_ffi/preamble.cmake +++ b/kernel-builder/src/pyproject/templates/tvm_ffi/preamble.cmake @@ -136,10 +136,56 @@ elseif(GPU_LANG STREQUAL "SYCL") message(STATUS "Using Intel SYCL C++ compiler: ${ICPX_COMPILER} and C compiler: ${ICX_COMPILER} Version: ${DPCPP_VERSION}") endif() + # --- SYCL fat-binary flags ------------------------------------------------ + # One .so carries an AOT image per GPU in SYCL_AOT_DEVICES plus a spir64 JIT + # fallback; the runtime picks the matching image at load time. + # These variables are the single source of truth: a dependency may change them + # and call xpu_compose_sycl_flags() again to rebuild the flags. + set(SYCL_OFFLOAD_TARGETS "spir64_gen,spir64") + set(SYCL_AOT_DEVICES "pvc,xe-lpg,ats-m150") + set(SYCL_AOT_BACKEND_OPTIONS " -cl-intel-enable-auto-large-GRF-mode -cl-poison-unsupported-fp64-kernels -cl-intel-greater-than-4GB-buffer-required") + set(SYCL_SPIRV_EXT "") + + # Rebuild sycl_flags (compile) and sycl_link_flags (link) from the variables + # above. A macro so it runs in the including scope and can be re-invoked. + # # -foffload-fp32-prec-* keeps fp32 division and sqrt IEEE correctly rounded, # matching PyTorch; both the compile and the link step need them. - set(sycl_link_flags "-Wl,-z,noexecstack;-fsycl;--offload-compress;-foffload-fp32-prec-div;-foffload-fp32-prec-sqrt;-fsycl-targets=spir64_gen,spir64;-Xs;-device pvc,xe-lpg,ats-m150 -options ' -cl-intel-enable-auto-large-GRF-mode -cl-poison-unsupported-fp64-kernels -cl-intel-greater-than-4GB-buffer-required';") - set(sycl_flags "-fPIC;-fsycl;-fhonor-nans;-fhonor-infinities;-fno-associative-math;-fno-approx-func;-foffload-fp32-prec-div;-foffload-fp32-prec-sqrt;-fno-sycl-instrument-device-code;--offload-compress;-fsycl-targets=spir64_gen,spir64;") + macro(xpu_compose_sycl_flags) + set(sycl_flags + "-fPIC;-fsycl;-fhonor-nans;-fhonor-infinities;-fno-associative-math;-fno-approx-func;-foffload-fp32-prec-div;-foffload-fp32-prec-sqrt;-fno-sycl-instrument-device-code;--offload-compress;-fsycl-targets=${SYCL_OFFLOAD_TARGETS}") + + # spir64_gen bakes the per-device AOT images; -device selects the GPUs. + set(sycl_link_flags + "-Wl,-z,noexecstack;-fsycl;--offload-compress;-foffload-fp32-prec-div;-foffload-fp32-prec-sqrt;-fsycl-targets=${SYCL_OFFLOAD_TARGETS}") + + # Backend options reach one target each: spir64_gen takes -device, the + # intel_gpu_* aliases imply theirs. SHELL: stops CMake from deduplicating + # the identical -options and silently dropping all but the first target. + string(REPLACE "," ";" _sycl_aot_targets "${SYCL_OFFLOAD_TARGETS}") + foreach(_tgt IN LISTS _sycl_aot_targets) + if(_tgt STREQUAL "spir64_gen") + string(APPEND sycl_link_flags + ";SHELL:-Xsycl-target-backend=spir64_gen \"-device ${SYCL_AOT_DEVICES} -options '${SYCL_AOT_BACKEND_OPTIONS}'\"") + elseif(_tgt MATCHES "^intel_gpu_") + string(APPEND sycl_link_flags + ";SHELL:-Xsycl-target-backend=${_tgt} \"-options '${SYCL_AOT_BACKEND_OPTIONS}'\"") + endif() + endforeach() + + # SYCL_SPIRV_EXT must be a COMPLETE list (translator replaces, not merges). + # A custom -spirv-ext only reaches an image whose triple matches the exact + # fsycl-targets alias, so emit one -Xspirv-translator= per target. + if(SYCL_SPIRV_EXT) + string(REPLACE "," ";" _sycl_ext_targets "${SYCL_OFFLOAD_TARGETS}") + foreach(_tgt IN LISTS _sycl_ext_targets) + string(APPEND sycl_link_flags + ";SHELL:-Xspirv-translator=${_tgt} -spirv-ext=${SYCL_SPIRV_EXT}") + endforeach() + endif() + endmacro() + + xpu_compose_sycl_flags() set(GPU_FLAGS "${sycl_flags}") add_compile_definitions(XPU_KERNEL) diff --git a/kernel-builder/src/pyproject/templates/xpu/dep-sycl-tla.cmake b/kernel-builder/src/pyproject/templates/xpu/dep-sycl-tla.cmake index 200364780..4dc8ff9e7 100644 --- a/kernel-builder/src/pyproject/templates/xpu/dep-sycl-tla.cmake +++ b/kernel-builder/src/pyproject/templates/xpu/dep-sycl-tla.cmake @@ -5,7 +5,8 @@ find_package(SyclTla) if(DPCPP_VERSION STREQUAL "2025.3") set(SYCL_TLA_REVISION "v0.8" CACHE STRING "sycl-tla revision to use") elseif(DPCPP_VERSION STREQUAL "2026.0") - set(SYCL_TLA_REVISION "v0.9.1" CACHE STRING "sycl-tla revision to use") + # v0.9.2 == the rev pinned in nix-builder; v0.9.1 has no cri kernel support. + set(SYCL_TLA_REVISION "v0.9.2" CACHE STRING "sycl-tla revision to use") else() message(FATAL_ERROR "Unknown DPCPP_VERSION: ${DPCPP_VERSION}") endif() @@ -68,12 +69,43 @@ if(SYCL_TLA_REVISION MATCHES "^v3\\.9") add_compile_definitions(OLD_API=1) endif() -string(REPLACE "-fsycl-targets=spir64_gen,spir64" "-fsycl-targets=spir64" sycl_link_flags "${sycl_link_flags}") -string(REPLACE "-device pvc,xe-lpg,ats-m150" "-device bmg_g21,pvc" sycl_link_flags "${sycl_link_flags}") -string(APPEND sycl_link_flags "-Xspirv-translator;-spirv-ext=+SPV_INTEL_split_barrier") +# Fat binary: AOT images for SYCL_AOT_DEVICES plus a spir64 JIT fallback. +# cri needs sycl-tla v0.9.2 and ocloc >= 26.22, so only 2026.0 gets AOT images. +if(DPCPP_VERSION STREQUAL "2026.0") + set(SYCL_AOT_DEVICES "{{ sycl_aot_devices }}") + set(SYCL_OFFLOAD_TARGETS "{{ sycl_offload_targets }}") +else() + set(SYCL_OFFLOAD_TARGETS "spir64") +endif() + +# sycl-tla needs extra extensions (split-barrier always; block-IO and +# matrix-multiply on newer DPCPP). Since the translator replaces the whole +# -spirv-ext list, we query the driver's defaults and append the extras. +set(_sycl_tla_extra_ext "+SPV_INTEL_split_barrier") if(DPCPP_VERSION STREQUAL "2025.2" OR DPCPP_VERSION STREQUAL "2025.3" OR DPCPP_VERSION STREQUAL "2026.0" OR SYCL_TLA_REVISION STREQUAL "v0.5") - string(APPEND sycl_link_flags ",+SPV_INTEL_2d_block_io,+SPV_INTEL_subgroup_matrix_multiply_accumulate") + string(APPEND _sycl_tla_extra_ext ",+SPV_INTEL_2d_block_io,+SPV_INTEL_subgroup_matrix_multiply_accumulate") endif() -string(REPLACE "-fsycl-targets=spir64_gen,spir64" "-fsycl-targets=spir64" sycl_flags "${sycl_flags}") + +set(_sycl_ext_probe "${CMAKE_CURRENT_BINARY_DIR}/_sycl_spirv_ext_probe.cpp") +file(WRITE "${_sycl_ext_probe}" "int main() { return 0; }\n") +# "-###" MUST be quoted: an unquoted # starts a CMake comment and would drop the +# rest of the COMMAND, making icpx read from stdin instead of dumping its flags. +execute_process( + COMMAND ${ICPX_COMPILER} -fsycl -fsycl-targets=spir64_gen "-###" "${_sycl_ext_probe}" + RESULT_VARIABLE _sycl_ext_probe_rc + OUTPUT_VARIABLE _sycl_ext_probe_out + ERROR_VARIABLE _sycl_ext_probe_err) +string(REGEX MATCH "-spirv-ext=[^\" ]+" _sycl_default_ext "${_sycl_ext_probe_out}${_sycl_ext_probe_err}") +if(_sycl_ext_probe_rc EQUAL 0 AND _sycl_default_ext) + # Strip the "-spirv-ext=-all," prefix, leaving the "+ext,+ext,..." default set. + string(REGEX REPLACE "^-spirv-ext=(-all,)?" "" _sycl_default_ext "${_sycl_default_ext}") + set(SYCL_SPIRV_EXT "${_sycl_default_ext},${_sycl_tla_extra_ext}") +else() + # Silently dropping the compiler defaults would ship a miscompiled kernel. + message(FATAL_ERROR "Could not determine default SPIR-V extensions from ${ICPX_COMPILER} " + "(exit ${_sycl_ext_probe_rc}): ${_sycl_ext_probe_err}") +endif() + +xpu_compose_sycl_flags() endif(GPU_LANG STREQUAL "SYCL") diff --git a/kernels-data/src/config/mod.rs b/kernels-data/src/config/mod.rs index 861c79390..776107d89 100644 --- a/kernels-data/src/config/mod.rs +++ b/kernels-data/src/config/mod.rs @@ -370,6 +370,13 @@ impl Kernel { } } + pub fn sycl_flags(&self) -> Option<&[String]> { + match self { + Kernel::Xpu { sycl_flags, .. } => sycl_flags.as_deref(), + _ => None, + } + } + pub fn backend(&self) -> Backend { match self { Kernel::Cpu { .. } => Backend::Cpu, diff --git a/nix-builder/pkgs/xpu-packages/ocloc.nix b/nix-builder/pkgs/xpu-packages/ocloc.nix index 80c02e167..d39cada0e 100644 --- a/nix-builder/pkgs/xpu-packages/ocloc.nix +++ b/nix-builder/pkgs/xpu-packages/ocloc.nix @@ -11,32 +11,32 @@ stdenv.mkDerivation (finalAttrs: { pname = "ocloc"; - version = "25.35"; + version = "26.22"; srcs = [ (fetchurl { - url = "https://github.com/intel/compute-runtime/releases/download/25.35.35096.9/intel-ocloc_25.35.35096.9-0_amd64.deb"; - hash = "sha256-AjzPj9iRKVi7PwCXcFbC+o3bzvjstLvHK9357LDuxvs="; + url = "https://github.com/intel/compute-runtime/releases/download/26.22.38646.4/intel-ocloc_26.22.38646.4-0_amd64.deb"; + hash = "sha256-JXRYQeZiecf/H/bC1NqeyRFoXBLhycVgnZnk1Uo2TcA="; }) (fetchurl { - url = "https://github.com/intel/intel-graphics-compiler/releases/download/v2.18.5/intel-igc-core-2_2.18.5+19820_amd64.deb"; - hash = "sha256-fDQPRcTylOyjqXgKGz7ObUtpn9xR59yf+MXWMjxdjWQ="; + url = "https://github.com/intel/intel-graphics-compiler/releases/download/v2.36.3/intel-igc-core-2_2.36.3+21719_amd64.deb"; + hash = "sha256-ngl1rHUBW0Meuy2oGoArn9HiijwnAxOpdWnNHmpsYEg="; }) (fetchurl { - url = "https://github.com/intel/intel-graphics-compiler/releases/download/v2.18.5/intel-igc-opencl-2_2.18.5+19820_amd64.deb"; - hash = "sha256-vLFDVIYXVnPxSxgO+4/Dn/MbdsYl4JsSU6B6cF78+cM="; + url = "https://github.com/intel/intel-graphics-compiler/releases/download/v2.36.3/intel-igc-opencl-2_2.36.3+21719_amd64.deb"; + hash = "sha256-NQpSMx54S7f7ntQumTtcRLfmVi/HTSzzECsptqV2+oU="; }) (fetchurl { - url = "https://github.com/intel/compute-runtime/releases/download/25.35.35096.9/intel-opencl-icd_25.35.35096.9-0_amd64.deb"; - hash = "sha256-ifJSVTyTeyRW7pkZhY/yq2Xcaw3L0hnHOVNUhGWt8yU="; + url = "https://github.com/intel/compute-runtime/releases/download/26.22.38646.4/intel-opencl-icd_26.22.38646.4-0_amd64.deb"; + hash = "sha256-b9rC6KKqz4ROv9kFIb9xArPrtE9pwbztGpeFp86Wo8I="; }) (fetchurl { - url = "https://github.com/intel/compute-runtime/releases/download/25.35.35096.9/libigdgmm12_22.8.1_amd64.deb"; - hash = "sha256-gQEU7wX01ExchvvC8LNGiBAvQVlqQHcqH/ekj132ns0="; + url = "https://github.com/intel/compute-runtime/releases/download/26.22.38646.4/libigdgmm12_22.10.0_amd64.deb"; + hash = "sha256-YDGmPW6KEs5hwU78FfLI5ycGEobjgguFlObQBhXgTVQ="; }) (fetchurl { - url = "https://github.com/intel/compute-runtime/releases/download/25.35.35096.9/libze-intel-gpu1_25.35.35096.9-0_amd64.deb"; - hash = "sha256-phfUqwNRqPJxdDi+QyXKARB1hFDhDrb6AtYUrtElIHo="; + url = "https://github.com/intel/compute-runtime/releases/download/26.22.38646.4/libze-intel-gpu1_26.22.38646.4-0_amd64.deb"; + hash = "sha256-i++fJOA/gm+TwHYIG9oTxqw6+9nkK5+48pj6tlIzDi8="; }) ]; dontStrip = true; diff --git a/nix-builder/pkgs/xpu-packages/sycl-tla.nix b/nix-builder/pkgs/xpu-packages/sycl-tla.nix index fbd6fc9d4..abfe74162 100644 --- a/nix-builder/pkgs/xpu-packages/sycl-tla.nix +++ b/nix-builder/pkgs/xpu-packages/sycl-tla.nix @@ -19,8 +19,8 @@ let hash = "sha256-xXAxIDBesjDDOIa6/YsGznyW+5+NpaO1L96lBuqRzrk="; }; "2026.0" = { - version = "0.9.1"; - hash = "sha256-c8ecf042tO9ChTiFav9vQvHhhVZyk1YH5govfWOxfF0="; + version = "0.9.2"; + hash = "sha256-Hn51Ah1wEscOnrt9O/aXBW7IC6Mcl4gUWynAmDeAOlM="; }; }; syclTlaVersion =