Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ build --flag_alias=release_dpc=@config//:release_dpc
build --flag_alias=device=@config//:device
build --flag_alias=cpu=@config//:cpu
build --flag_alias=enable_assert=@config//:enable_assert
build --flag_alias=rng_backend=@config//:rng_backend

# Always pass this env variable to test rules, because SYCL
# OpenCL backend uses it to determine available devices
Expand Down
27 changes: 22 additions & 5 deletions .ci/env/bazelisk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,23 @@
#===============================================================================

BAZELISK_VERSION=v1.29.0

# Bazelisk itself always runs on the CI *exec* host (even when the build
# cross-compiles to another target arch, e.g. the riscv64 job below), so pick
# the asset matching the host running this script, not the oneDAL target arch.
case "$(uname -m)" in
x86_64|amd64)
BAZELISK_ASSET=bazelisk-linux-amd64
;;
aarch64|arm64)
BAZELISK_ASSET=bazelisk-linux-arm64
;;
*)
echo ":error: Unsupported host architecture for Bazelisk: $(uname -m)" >&2
exit 1
;;
esac

# collect information about the bazelisk release
BAZELISK_JSON=$(wget -qO- \
--header="Accept: application/vnd.github+json" \
Expand All @@ -31,22 +48,22 @@ fi
SHA256=""
found=""
while IFS= read -r line; do
if [[ $line == *'"name": "bazelisk-linux-amd64"'* ]]; then
if [[ $line == *"\"name\": \"${BAZELISK_ASSET}\""* ]]; then
found=1
elif [[ $found && $line == *'"digest":'* ]]; then
SHA256=$(echo "$line" | sed -n 's/.*"sha256:\([^"]*\)".*/\1/p')
break
fi
done < <(printf '%s\n' "$BAZELISK_JSON")
SHA256+=" bazelisk-linux-amd64"
SHA256+=" ${BAZELISK_ASSET}"

# Download Bazelisk
wget https://github.com/bazelbuild/bazelisk/releases/download/$BAZELISK_VERSION/bazelisk-linux-amd64
wget https://github.com/bazelbuild/bazelisk/releases/download/$BAZELISK_VERSION/${BAZELISK_ASSET}
echo $SHA256
echo ${SHA256} | sha256sum --check
# "Install" bazelisk
chmod +x bazelisk-linux-amd64
chmod +x ${BAZELISK_ASSET}
mkdir -p bazel/bin
mv bazelisk-linux-amd64 bazel/bin/bazel
mv ${BAZELISK_ASSET} bazel/bin/bazel
export BAZEL_VERSION=$(./bazel/bin/bazel --version | awk '{print $2}')
export PATH=$PATH:$(pwd)/bazel/bin
64 changes: 64 additions & 0 deletions .ci/pipeline/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,70 @@ jobs:
fi
displayName: 'bazel-cache-limit'

- job: 'LinuxBazelGNU_OpenBLAS_rv64'
timeoutInMinutes: 0
variables:
OPENBLAS_VERSION : 'v0.3.27'
OPENBLAS_CACHE_DIR : $(Pipeline.Workspace)/openblas-riscv64-clang
SYSROOT_CACHE_DIR: $(Pipeline.Workspace)/sysroot-riscv64
pool:
vmImage: 'ubuntu-24.04'
steps:
- script: |
.ci/env/apt.sh dev-base
displayName: 'apt-get install'
- script: |
.ci/env/apt.sh gnu-cross-compilers riscv64
displayName: 'riscv64-compiler installation'
- script: |
.ci/env/apt.sh llvm-version 18
displayName: 'llvm 18 installation'
- script: |
# sourcing done to set bazel version value from script
source .ci/env/bazelisk.sh
echo "##vso[task.setvariable variable=BAZEL_VERSION]${BAZEL_VERSION}"
displayName: 'install-bazel'
- script: |
.ci/scripts/describe_system.sh
displayName: 'System info'
- task: Cache@2
inputs:
key: '"riscv64" | "sysroot" | "$(SYSROOT_OS)"'
path: $(SYSROOT_CACHE_DIR)
cacheHitVar: SYSROOT_RESTORED
- script: |
.ci/env/apt.sh build-sysroot $(Pipeline.Workspace) riscv64 $(SYSROOT_OS) sysroot-riscv64
displayName: 'Build riscv64 sysroot'
condition: ne(variables.SYSROOT_RESTORED, 'true')
- task: Cache@2
inputs:
key: '"clang" | "riscv64" | "openblas" | "$(OPENBLAS_VERSION)" | "ILP64" | "$(SYSROOT_OS)"'
path: $(OPENBLAS_CACHE_DIR)
cacheHitVar: OPENBLAS_RESTORED
- script: |
# Build OpenBLAS with clang + the riscv64 sysroot, matching
# LinuxMakeLLVM_OpenBLAS_rv64 (same cache key => shared cache hit). The
# gnu riscv64 cross-gcc on the ubuntu-24.04 image is gcc-13, which lacks
# the RVV segment intrinsics (vfloat32m4x2_t, __riscv_vlseg2e32_v_f32m4x2)
# that OpenBLAS' RISCV64_ZVL128B kernels use, so it cannot build them.
.ci/env/openblas.sh --target RISCV64_ZVL128B --host-compiler gcc --compiler clang --target-arch riscv64 --cross-compile --prefix $(OPENBLAS_CACHE_DIR) --sysroot $(SYSROOT_CACHE_DIR) --version $(OPENBLAS_VERSION)
displayName: 'Build OpenBLAS'
condition: ne(variables.OPENBLAS_RESTORED, 'true')
- script: |
export CC=riscv64-linux-gnu-gcc
export CXX=riscv64-linux-gnu-g++
export OPENBLASROOT=$(OPENBLAS_CACHE_DIR)
bazel build --platforms=@config//:linux_riscv64 --backend_config=ref \
//cpp/daal:core_dynamic //cpp/oneapi/dal:dynamic
displayName: 'bazel build (riscv64 cross)'
- script: |
set -euo pipefail
for lib in bazel-bin/cpp/daal/libonedal_core.so bazel-bin/cpp/oneapi/dal/libonedal.so; do
file "${lib}"
readelf -h "${lib}" | grep -q "RISC-V" || { echo "##vso[task.logissue type=error]${lib} is not a RISC-V ELF"; exit 1; }
done
displayName: 'Verify RISC-V ELF output'

- job: 'LinuxReleaseCompare'
dependsOn:
- LinuxMakeGNU_MKL
Expand Down
51 changes: 50 additions & 1 deletion .github/workflows/ci-aarch64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,61 @@ jobs:
env:
CMAKE_GENERATOR: Ninja

bazel-build-and-test:
strategy:
fail-fast: false
matrix:
os: [
{ name: GitHub hosted, label: ubuntu-24.04-arm },
]
rng: [ ref, openrng ]

name: LinuxBazel_OpenBLAS(SVE)${{ matrix.rng == 'openrng' && '_OpenRNG' || '' }}-${{ matrix.os.name }}
if: github.repository == 'uxlfoundation/oneDAL'
runs-on: ${{ matrix.os.label }}
steps:
- name: Checkout oneDAL
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Install Bazel
run: |
source .ci/env/bazelisk.sh
echo "$(pwd)/bazel/bin" >> "$GITHUB_PATH"

- name: Build OpenBLAS
run: |
.ci/env/openblas.sh
echo "OPENBLASROOT=$(pwd)/__deps/openblas_aarch64" >> "$GITHUB_ENV"

- name: Build OpenRNG
if: matrix.rng == 'openrng'
run: |
.ci/env/openrng.sh --version ${{ env.OPENRNG_VERSION }}
echo "OPENRNGROOT=$(pwd)/__deps/openrng" >> "$GITHUB_ENV"

- name: System Info
run: .ci/scripts/describe_system.sh

- name: bazel build core_dynamic
run: |
bazel build --platforms=@config//:linux_aarch64 --backend_config=ref \
--rng_backend=${{ matrix.rng }} \
//cpp/daal:core_dynamic //cpp/oneapi/dal:dynamic

- name: Verify AArch64 ELF output
run: |
set -euo pipefail
for lib in bazel-bin/cpp/daal/libonedal_core.so bazel-bin/cpp/oneapi/dal/libonedal.so; do
file "${lib}"
readelf -h "${lib}" | grep -q "AArch64" || { echo "::error::${lib} is not an AArch64 ELF"; exit 1; }
done

# This job adds a check named "CI AArch64" that represents overall
# workflow status and can be used in branch rulesets. This is useful when
# running a matrix CI, and allows changing the CI without needing to change
# the overall required check name.
status:
needs: [build-and-test, openrng-build-and-test]
needs: [build-and-test, openrng-build-and-test, bazel-build-and-test]
runs-on: ubuntu-latest
name: "CI AArch64"
steps:
Expand Down
3 changes: 3 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ openmp_repo(
openblas_repo = use_repo_rule("@onedal//dev/bazel/deps:openblas.bzl", "openblas_repo")
openblas_repo(name = "openblas", root_env_var = "OPENBLASROOT",)

openrng_repo = use_repo_rule("@onedal//dev/bazel/deps:openrng.bzl", "openrng_repo")
openrng_repo(name = "openrng", root_env_var = "OPENRNGROOT",)

tbb_repo = use_repo_rule("@onedal//dev/bazel/deps:tbb.bzl", "tbb_repo")
tbb_repo(
name = "tbb",
Expand Down
10 changes: 10 additions & 0 deletions cpp/daal/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,18 @@ daal_module(
"@config//:backend_ref": False,
"//conditions:default": True,
}),
# Matches dev/make/deps.ref.mk: RNG_OPENRNG links libopenrng.a alongside
# OpenBLAS. (The OPENRNG_BACKEND compile define is set globally in
# daal.bzl's daal_module, since service_rng_ref.h is consumed by many
# compiled modules, not just this one.)
deps = select({
"@config//:backend_ref": [ "@openblas//:openblas",
],
"//conditions:default": [ "@mkl//:mkl_core",
],
}) + select({
"@config//:rng_backend_openrng": [ "@openrng//:openrng" ],
"//conditions:default": [],
}),
Comment on lines 42 to 50
)

Expand Down Expand Up @@ -77,6 +84,9 @@ daal_module(
":public_includes",
"@mkl//:headers",
],
}) + select({
"@config//:rng_backend_openrng": [ "@openrng//:headers" ],
"//conditions:default": [],
}),
)

Expand Down
26 changes: 26 additions & 0 deletions dev/bazel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -654,3 +654,29 @@ build --linkopt=-your-link-flag
| `COPT=-flag` | `--copt=-flag` (C+C++) / `--cxxopt=-flag` (C++ only) | Arbitrary compiler flag |
| `PLAT=<isa>` | `--cpu=<isa>` | ISA selection |
| Full CPU ISA release coverage | `bazel build //:release --cpu=all` | Build all supported CPU ISA variants |
| `PLAT=lnxarm` | `--platforms=@config//:linux_aarch64 CC=aarch64-linux-gnu-gcc`| Cross-compile to Linux AArch64 (ref backend only) |
| `PLAT=lnxriscv64` | `--platforms=@config//:linux_riscv64 CC=riscv64-linux-gnu-gcc`| Cross-compile to Linux RISC-V64 (ref backend only) |
| `RNG_BACKEND=openrng` | `--rng_backend=openrng` | Use OpenRNG instead of the `<random>`-based ref RNG (requires `OPENRNGROOT`)|

## Cross-compiling to ARM/RISC-V

AArch64 and RISC-V64 are only supported with the `ref` backend (`--backend_config=ref`),
matching the Makefile's `PLAT=lnxarm`/`PLAT=lnxriscv64`. Both ship a single fixed
ISA variant (SVE / RVGC) — there is no runtime CPU dispatch like on x86.

```sh
# AArch64
CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ \
bazel build --platforms=@config//:linux_aarch64 --backend_config=ref \
//cpp/daal:core_dynamic

# RISC-V64
CC=riscv64-linux-gnu-gcc CXX=riscv64-linux-gnu-g++ \
bazel build --platforms=@config//:linux_riscv64 --backend_config=ref \
//cpp/daal:core_dynamic
```

`OPENBLASROOT` must point at an OpenBLAS install built for the target arch (see
`.ci/env/openblas.sh`). To use the OpenRNG backend instead of the ref RNG (currently
validated on ARM), also set `--rng_backend=openrng` and point `OPENRNGROOT` at an
OpenRNG install built with `.ci/env/openrng.sh`.
8 changes: 6 additions & 2 deletions dev/bazel/cc/compile.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,14 @@ def _compile(name, ctx, toolchain, feature_config, compilation_contexts=[],
cpu_to_file_dict = _normalize_cpu_files(sources_by_category.cpu_files,
sources_by_category.special_cpu_files)
for cpu in cpus:
# `cpu_to_file_dict` only ever has entries for the x86 ISA IDs
# that `_CPU_SUFFIX_TO_ISA_MAP` knows about (_nrh/_hsw/_skx); on
# ARM/RISC-V (cpu == "sve"/"rv64") there is no such per-ISA
# source-file split, so fall back to the general `_cpu` files.
srcs = cpu_to_file_dict.get(cpu, sources_by_category.cpu_files) if cpu_to_file_dict else sources_by_category.cpu_files
compilation_context, compulation_output = _compile_wrapper(
name + "_" + cpu, ctx, toolchain, cpu_feature_configs[cpu],
srcs = (cpu_to_file_dict[cpu] if cpu_to_file_dict else
sources_by_category.cpu_files),
srcs = srcs,
local_defines = local_defines + cpu_defines[cpu],
compilation_contexts = dep_compilation_contexts,
**kwargs,
Expand Down
64 changes: 52 additions & 12 deletions dev/bazel/config/config.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#===============================================================================

load("@onedal//dev/bazel:utils.bzl", "utils", "sets")
load("@onedal//dev/bazel/toolchains:common.bzl", "detect_os", "detect_host_arch", "detect_target_arch")

_BINARY_MAJOR = "4"
_BINARY_MINOR = "0"
Expand Down Expand Up @@ -77,40 +78,75 @@ CpuInfo = provider(
],
)

_ISA_EXTENSIONS = ["sse2", "avx2", "avx512"]
_ISA_EXTENSIONS_MODERN = ["sse2", "avx2", "avx512"]
_ISA_EXTENSIONS_X86 = ["sse2", "avx2", "avx512"]
_ISA_EXTENSIONS_X86_MODERN = ["sse2", "avx2", "avx512"]
_ISA_EXTENSIONS_ARM = ["sve"]
_ISA_EXTENSIONS_RISCV64 = ["rv64"]
_ISA_EXTENSION_AUTO_DEFAULT = "avx2"

def _check_cpu_extensions(extensions):
allowed = sets.make(_ISA_EXTENSIONS)
_ARCH_TO_ISA_EXTENSIONS = {
"arm": _ISA_EXTENSIONS_ARM,
"riscv64": _ISA_EXTENSIONS_RISCV64,
}

def _get_allowed_isa_extensions(ctx):
# x86 has multiple ISA variants with runtime dispatch; ARM/RISC-V
# currently ship exactly one fixed variant (see cpp/daal/src/services/cpu_type.h),
# so their `allowed` list is a single value.
#
# `cpu_info` is a `build_setting` rule; Bazel trims `PlatformOptions`
# from build-setting configurations for cross-config cache sharing, so
# `ctx.target_platform_has_constraint` is not reliable here. The arch is
# instead resolved once at repository-rule time (see
# `_declare_onedal_config_impl`) from the same `CC`/`CXX` cross-compiler
# triple prefix that `dev/bazel/toolchains/cc_toolchain.bzl` uses, and
# threaded in through the `arch` attribute.
return _ARCH_TO_ISA_EXTENSIONS.get(ctx.attr.arch, _ISA_EXTENSIONS_X86)

def _check_cpu_extensions(extensions, allowed):
allowed_set = sets.make(allowed)
requested = sets.make(extensions)
unsupported = sets.to_list(sets.difference(requested, allowed))
unsupported = sets.to_list(sets.difference(requested, allowed_set))
if unsupported:
fail("Unsupported CPU extensions: {}\n".format(unsupported) +
"Allowed extensions: {}".format(_ISA_EXTENSIONS))
"Allowed extensions: {}".format(allowed))

def _cpu_info_impl(ctx):
allowed = _get_allowed_isa_extensions(ctx)
is_x86 = allowed == _ISA_EXTENSIONS_X86
if ctx.build_setting_value == "all":
isa_extensions = _ISA_EXTENSIONS
isa_extensions = _ISA_EXTENSIONS_X86_MODERN if is_x86 else allowed
elif ctx.build_setting_value == "modern":
isa_extensions = _ISA_EXTENSIONS_MODERN
isa_extensions = _ISA_EXTENSIONS_X86_MODERN if is_x86 else allowed
elif ctx.build_setting_value == "auto":
isa_extensions = [ ctx.attr.auto_cpu ]
# `auto_cpu` reflects the exec host's CPU probe, which is only
# meaningful for a native x86 build. ARM/RISC-V always builds their
# single supported variant regardless of the exec host.
isa_extensions = [ ctx.attr.auto_cpu ] if is_x86 else allowed
else:
isa_extensions = ctx.build_setting_value.split(" ")
isa_extensions = [x.strip() for x in isa_extensions]
isa_extensions = utils.unique(["sse2"] + isa_extensions)
_check_cpu_extensions(isa_extensions)
if is_x86:
# sse2 is the runtime-dispatch fallback variant on x86 and is always built.
isa_extensions = utils.unique(["sse2"] + isa_extensions)
else:
isa_extensions = utils.unique(isa_extensions)
_check_cpu_extensions(isa_extensions, allowed)
return CpuInfo(
enabled = isa_extensions,
allowed = _ISA_EXTENSIONS,
allowed = allowed,
)

cpu_info = rule(
implementation = _cpu_info_impl,
build_setting = config.string(flag = True),
attrs = {
"auto_cpu": attr.string(mandatory=True),
# oneDAL arch ID (arm/riscv64/intel64), matching
# dev/bazel/toolchains/common.bzl's detect_target_arch. Baked in at
# repository-rule time since this rule's own configuration cannot
# see `--platforms` (see _get_allowed_isa_extensions).
"arch": attr.string(mandatory=True),
"verbose": attr.label(),
},
)
Expand Down Expand Up @@ -217,12 +253,15 @@ def _detect_cpu_extension(repo_ctx):

def _declare_onedal_config_impl(repo_ctx):
auto_cpu = _detect_cpu_extension(repo_ctx)
os_id = detect_os(repo_ctx)
target_arch = detect_target_arch(repo_ctx, detect_host_arch(repo_ctx, os_id))

repo_ctx.template(
"BUILD",
Label("@onedal//dev/bazel/config:config.tpl.BUILD"),
substitutions = {
"%{auto_cpu}": auto_cpu,
"%{arch}": target_arch,
"%{version_major}": "2026",
"%{version_minor}": "2",
"%{version_update}": "0",
Expand All @@ -236,6 +275,7 @@ def _declare_onedal_config_impl(repo_ctx):
declare_onedal_config = repository_rule(
implementation = _declare_onedal_config_impl,
local = True,
environ = ["CC", "CXX"],
attrs = {
"_cpudetect_src": attr.label(
default = "@onedal//dev/bazel/config:cpudetect.cpp",
Expand Down
Loading
Loading