Skip to content

Commit e19dbc4

Browse files
dynamic linkage with mkl(sycl) in bazel (#3285)
1 parent 0d5324e commit e19dbc4

File tree

8 files changed

+183
-33
lines changed

8 files changed

+183
-33
lines changed

MODULE.bazel

Lines changed: 94 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,25 +114,109 @@ dpl_repo(
114114
"onedpl_devel-2022.7.1.data/data",
115115
],
116116
)
117-
117+
118+
# oneMKL dependencies for Bazel build.
119+
#
120+
# NOTE:
121+
# PyPI packages provide only the versioned .so files (e.g., libmkl_blas_sycl.so.5),
122+
# but for building and linking we also need the unversioned symlinks (e.g., libmkl_blas_sycl.so).
123+
# Anaconda packages provide both, so we use them to ensure proper dynamic linking.
124+
#
118125
mkl_repo = use_repo_rule("@onedal//dev/bazel/deps:mkl.bzl", "mkl_repo")
119126
mkl_repo(
120127
name = "mkl",
121128
root_env_var = "MKLROOT",
122129
urls = [
123-
"https://files.pythonhosted.org/packages/95/d8/76f53cde7c1df06fcd153b4f6fdf0516aafbfc3239ba8d5a8c354e20bbb2/mkl_static-2025.0.0-py2.py3-none-manylinux_2_28_x86_64.whl",
124-
"https://files.pythonhosted.org/packages/b1/91/b76ab204c03f90d5ce008ba7cf6efd77168059866e96b70277fec959b940/mkl_include-2025.0.0-py2.py3-none-manylinux_2_28_x86_64.whl",
125-
"https://files.pythonhosted.org/packages/b8/d7/ea82194db165d83e22dfedee4d45423477441202e2c321b9e96809d36e63/mkl_devel_dpcpp-2025.0.0-py2.py3-none-manylinux_2_28_x86_64.whl",
130+
# Due to issues with dispatcher, its not possible to use dynamic mkl core in bazel
131+
# There are conflicts between avx512/avx2/cm3/def symbols in cc_library
132+
# TODO: investigate the how to provide global runtime dependencies in bazel.
133+
# Core static MKL runtime libraries (.a)
134+
# Includes libmkl_intel_lp64.a, libmkl_core.a, libmkl_sequential.a, etc.
135+
"https://anaconda.org/conda-forge/mkl-static/2024.2.2/download/linux-64/mkl-static-2024.2.2-ha770c72_17.conda",
136+
137+
# Header files for classic MKL (C/C++) interface(mkl_include_)
138+
# Contains "mkl.h" and related headers, not using oneAPI directory structure
139+
"https://files.pythonhosted.org/packages/11/58/6f583b3bac7d3952a89a00ab34e61baa17f6d6de3454a8005958289bef22/mkl_include-2025.2.0-py2.py3-none-manylinux_2_28_x86_64.whl",
140+
141+
# oneMKL SYCL C++ headers (DPC++/SYCL interface)
142+
# Provides headers for SYCL-based oneAPI MKL development (e.g., onemkl/*.hpp)
143+
"https://files.pythonhosted.org/packages/67/60/183badc2d807be1abb95a20315e84a2075cb44a1d1ede104d42cb1ed3092/onemkl_sycl_include-2025.2.0-py2.py3-none-manylinux_2_28_x86_64.whl",
144+
145+
# oneMKL SYCL - main part
146+
# Provides libmkl_sycl.so
147+
"https://files.pythonhosted.org/packages/08/30/a28cfc8f9a982a5998940b808288f58f4ba2607e50a18f97207b7428f602/mkl_devel_dpcpp-2025.2.0-py2.py3-none-manylinux_2_28_x86_64.whl",
148+
149+
# oneMKL SYCL - Data Fitting domain
150+
# Provides libmkl_sycl_data_fitting.so.5 for interpolation, regression, etc.
151+
"https://anaconda.org/conda-forge/onemkl-sycl-datafitting/2025.2.0/download/linux-64/onemkl-sycl-datafitting-2025.2.0-haf5e11a_628.conda",
152+
153+
# oneMKL SYCL - BLAS domain
154+
# Provides libmkl_sycl_blas.so.5 with SYCL-enabled BLAS (e.g., GEMM, AXPY)
155+
"https://anaconda.org/conda-forge/onemkl-sycl-blas/2025.2.0/download/linux-64/onemkl-sycl-blas-2025.2.0-haf5e11a_628.conda",
156+
157+
# oneMKL SYCL - DFT domain
158+
# Provides libmkl_sycl_dft.so.5 for Discrete Fourier Transform operations
159+
"https://anaconda.org/conda-forge/onemkl-sycl-dft/2025.2.0/download/linux-64/onemkl-sycl-dft-2025.2.0-haf5e11a_628.conda",
160+
161+
# oneMKL SYCL - LAPACK domain
162+
# Provides libmkl_sycl_lapack.so.5 for linear algebra (e.g., LU, QR, eigenvalues)
163+
"https://anaconda.org/conda-forge/onemkl-sycl-lapack/2025.2.0/download/linux-64/onemkl-sycl-lapack-2025.2.0-haf5e11a_628.conda",
164+
165+
# oneMKL SYCL - Sparse domain
166+
# Provides libmkl_sycl_sparse.so.5 for sparse matrix operations and solvers
167+
"https://anaconda.org/conda-forge/onemkl-sycl-sparse/2025.2.0/download/linux-64/onemkl-sycl-sparse-2025.2.0-haf5e11a_628.conda",
168+
169+
# oneMKL SYCL - Random Number Generator (RNG)
170+
# Provides libmkl_sycl_rng.so.5 for random number generation with SYCL
171+
"https://anaconda.org/conda-forge/onemkl-sycl-rng/2025.2.0/download/linux-64/onemkl-sycl-rng-2025.2.0-haf5e11a_628.conda",
172+
173+
# oneMKL SYCL - Vector Math (VM)
174+
# Provides libmkl_sycl_vm.so.5 for fast element-wise math operations
175+
"https://anaconda.org/conda-forge/onemkl-sycl-vm/2025.2.0/download/linux-64/onemkl-sycl-vm-2025.2.0-haf5e11a_628.conda",
176+
177+
# oneMKL SYCL - Statistics domain
178+
# Provides libmkl_sycl_stats.so.5 for statistical computations and analysis
179+
"https://anaconda.org/conda-forge/onemkl-sycl-stats/2025.2.0/download/linux-64/onemkl-sycl-stats-2025.2.0-haf5e11a_628.conda",
126180
],
127181
sha256s = [
128-
"706f92fcd6e00cc94155097a87528da52b4c3dda4616c8c334963251773a0d13",
129-
"cf19e274bdd1449ef7285671576c545510bebff669363ee1926779192f618cdd",
130-
"455281a590920fb58628dbc06ac007f2618c7315e4c04748c2a1b62efa01afb3",
182+
# Core static MKL runtime libraries (.a)
183+
"c34ecf9d3b7371b4e9b0dfd9cf55daedf2c884507a88d4fc3fe98bf862092b74",
184+
# Header files for classic MKL (C/C++) interface(mkl_include)
185+
"691ceaccf6d960e19d47304d24ca2ee4e807810077e93c1c86c2e32cd6223012",
186+
# oneMKL SYCL C++ headers (DPC++/SYCL interface)
187+
"4e995c02e5f43265aa830a06e538b2e5ada76b7c2785c26b788d6073ba605b0f",
188+
# oneMKL SYCL - main part
189+
"44ceb849a99f9bbe3ad89dac9dcdedb540b3996c69e699a40047d62d51934a0c",
190+
# oneMKL SYCL - Data Fitting domain
191+
"84c196a6e243a6f275aa0f040ba02f12d8e9e9bfb5b02f5e58c3160f9bf52887",
192+
# oneMKL SYCL - BLAS domain
193+
"0748e4f91e328f4ae995013b10ae79966f80cf62a72e76495dfe1841cd022235",
194+
# oneMKL SYCL - DFT domain
195+
"3580e30db302602e89e54a0296457dbdafbccd86fe79975f3bf84be0d3ce57c1",
196+
# oneMKL SYCL - LAPACK domain
197+
"e56ec1e4e0fbfa28783a28e99337ca541934cb3aaaa0ecca469a27dab2f3a762",
198+
# oneMKL SYCL - Sparse domain
199+
"b2cdba1894464927a05115c04bcc1a5b64e25c116c45ae44c75990c101162b35",
200+
# oneMKL SYCL - Random Number Generator (RNG)
201+
"e5664adaca1c2e15a771b0d67ec7691137c8ba8e0a5a6af6fdffece9ae37692e",
202+
# oneMKL SYCL - Vector Math (VM)
203+
"ed782c632d4851f98303ab34f47437cbb77d4b9f705b36b62d4b05123c629604",
204+
# oneMKL SYCL - Statistics domain
205+
"ebf80b94fad4483124c62686b00552b4024e4ec987c83483b4533902a7b854a4",
131206
],
132207
strip_prefixes = [
133-
"mkl_static-2025.0.0.data/data",
134-
"mkl_include-2025.0.0.data/data",
135-
"mkl_devel_dpcpp-2025.0.0.data/data",
208+
"mkl_static-2025.2.0.data/data",
209+
"mkl_include-2025.2.0.data/data",
210+
"onemkl_sycl_include-2025.2.0.data/data",
211+
"mkl_devel_dpcpp-2025.2.0.data/data",
212+
"onemkl_sycl_datafitting-2025.2.0.data/data",
213+
"onemkl_sycl_blas-2025.2.0.data/data",
214+
"onemkl_sycl_dft-2025.2.0.data/data",
215+
"onemkl_sycl_lapack-2025.2.0.data/data",
216+
"onemkl_sycl_sparse-2025.2.0.data/data",
217+
"onemkl_sycl_rng-2025.2.0.data/data",
218+
"onemkl_sycl_vm-2025.2.0.data/data",
219+
"onemkl_sycl_stats-2025.2.0.data/data",
136220
],
137221
)
138222

cpp/daal/BUILD

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ daal_module(
1818
deps = select({
1919
"@config//:backend_ref": [ ],
2020
"//conditions:default": [
21-
"@mkl//:mkl_thr",
21+
"@mkl//:mkl_core",
2222
],
2323
}),
2424
)
@@ -29,7 +29,7 @@ daal_module(
2929
deps = select({
3030
"@config//:backend_ref": [ "@openblas//:openblas",
3131
],
32-
"//conditions:default": [ "@mkl//:mkl_thr",
32+
"//conditions:default": [ "@mkl//:mkl_core",
3333
],
3434
}),
3535
)

cpp/oneapi/dal/test/engine/mkl/BUILD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ dal_test_module(
1313
extra_deps = [{
1414
"@config//:backend_ref": [ "@openblas//:openblas",
1515
],
16-
"//conditions:default": [ "@mkl//:mkl_thr",
16+
"//conditions:default": [ "@mkl//:mkl_core",
1717
],
1818
}],
1919
)

dev/bazel/deps/mkl.bzl

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,30 @@ mkl_repo = repos.prebuilt_libs_repo_rule(
2424
"lib/libmkl_core.a",
2525
"lib/libmkl_intel_ilp64.a",
2626
"lib/libmkl_tbb_thread.a",
27-
"lib/libmkl_sycl.a",
27+
"lib/libmkl_sycl.so",
28+
"lib/libmkl_sycl_blas.so",
29+
"lib/libmkl_sycl_lapack.so",
30+
"lib/libmkl_sycl_sparse.so",
31+
"lib/libmkl_sycl_dft.so",
32+
"lib/libmkl_sycl_vm.so",
33+
"lib/libmkl_sycl_rng.so",
34+
"lib/libmkl_sycl_stats.so",
35+
"lib/libmkl_sycl_data_fitting.so",
36+
"lib/libmkl_sycl_blas.so.5",
37+
"lib/libmkl_sycl_lapack.so.5",
38+
"lib/libmkl_sycl_sparse.so.5",
39+
"lib/libmkl_sycl_dft.so.5",
40+
"lib/libmkl_sycl_vm.so.5",
41+
"lib/libmkl_sycl_rng.so.5",
42+
"lib/libmkl_sycl_stats.so.5",
43+
"lib/libmkl_sycl_data_fitting.so.5",
2844
],
2945
build_template = "@onedal//dev/bazel/deps:mkl.tpl.BUILD",
3046
download_mapping = {
3147
# Required directory layout and layout in the downloaded
3248
# archives may be different. Mapping helps to setup relations
3349
# between required layout (LHS) and downloaded (RHS).
34-
# In this case, files from `lib/*` will be copied to `lib/intel64/*`.
35-
"lib/intel64": "lib/",
50+
# For example in this case, files from `lib/*` will be copied to `lib/intel64/*`.
51+
# "lib/intel64": "lib/",
3652
},
3753
)

dev/bazel/deps/mkl.tpl.BUILD

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ cc_library(
1515
)
1616

1717
cc_library(
18-
name = "mkl_core",
18+
name = "mkl_static",
1919
srcs = [
2020
"lib/libmkl_core.a",
2121
"lib/libmkl_intel_ilp64.a",
@@ -37,21 +37,44 @@ cc_library(
3737
":headers",
3838
"@opencl//:opencl_binary",
3939
],
40-
alwayslink = 1,
41-
linkstatic = 1,
4240
)
4341

4442
cc_library(
45-
name = "mkl_thr",
43+
name = "mkl_core",
4644
linkopts = [
4745
"-lpthread",
4846
],
4947
deps = [
5048
":headers",
51-
":mkl_core",
49+
":mkl_static",
5250
]
5351
)
5452

53+
cc_library(
54+
name = "mkl_dpc_utils",
55+
linkopts = [
56+
"-fsycl-max-parallel-link-jobs=16",
57+
],
58+
srcs = [
59+
"lib/libmkl_sycl_blas.so",
60+
"lib/libmkl_sycl_lapack.so",
61+
"lib/libmkl_sycl_sparse.so",
62+
"lib/libmkl_sycl_dft.so",
63+
"lib/libmkl_sycl_vm.so",
64+
"lib/libmkl_sycl_rng.so",
65+
"lib/libmkl_sycl_stats.so",
66+
"lib/libmkl_sycl_data_fitting.so",
67+
"lib/libmkl_sycl_blas.so.5",
68+
"lib/libmkl_sycl_lapack.so.5",
69+
"lib/libmkl_sycl_sparse.so.5",
70+
"lib/libmkl_sycl_dft.so.5",
71+
"lib/libmkl_sycl_vm.so.5",
72+
"lib/libmkl_sycl_rng.so.5",
73+
"lib/libmkl_sycl_stats.so.5",
74+
"lib/libmkl_sycl_data_fitting.so.5",
75+
],
76+
)
77+
5578
cc_library(
5679
name = "mkl_dpc",
5780
# TODO: add a mechanism to get attr from bazel command(it's not available for now)
@@ -61,9 +84,10 @@ cc_library(
6184
"-fsycl-max-parallel-link-jobs=16",
6285
],
6386
srcs = [
64-
"lib/libmkl_sycl.a",
87+
"lib/libmkl_sycl.so",
6588
],
6689
deps = [
6790
":headers",
91+
":mkl_dpc_utils",
6892
],
6993
)

dev/bazel/deps/onedal.tpl.BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ cc_library(
1919
# TODO: Currently vml_ipp lib depends on TBB, but it shouldn't
2020
# Remove TBB from deps once problem with vml_ipp is resolved
2121
"@tbb//:tbb_binary",
22+
"@mkl//:mkl_core",
2223
],
2324
)
2425

@@ -87,6 +88,7 @@ cc_library(
8788
# TODO: Currently vml_ipp lib depends on TBB, but it shouldn't
8889
# Remove TBB from deps once problem with vml_ipp is resolved
8990
"@tbb//:tbb_binary",
91+
"@mkl//:mkl_core",
9092
],
9193
)
9294

dev/bazel/repos.bzl

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,41 @@ load("@onedal//dev/bazel:utils.bzl", "utils", "paths")
1919
def _download_and_extract(repo_ctx, url, sha256, output, strip_prefix):
2020
# Workaround Python wheel extraction. Bazel cannot determine file
2121
# type automatically as does not support wheels out-of-the-box.
22-
archive_type = ""
23-
if url.endswith(".whl"):
24-
archive_type = "zip"
25-
repo_ctx.download_and_extract(
22+
filename = url.split("/")[-1]
23+
downloaded_path = repo_ctx.path(filename)
24+
25+
repo_ctx.download(
2626
url = url,
27+
output = downloaded_path,
2728
sha256 = sha256,
28-
output = output,
29-
stripPrefix = strip_prefix,
30-
type = archive_type,
3129
)
3230

31+
if filename.endswith(".conda"):
32+
repo_ctx.execute(["unzip", downloaded_path, "-d", output])
33+
34+
for entry in repo_ctx.path(output).readdir():
35+
if entry.basename.startswith("pkg-") and entry.basename.endswith(".tar.zst"):
36+
repo_ctx.execute(["bash", "-c", "unzstd '%s' --stdout | tar -xf - -C '%s'" % (entry, output)])
37+
38+
elif filename.endswith(".whl") or filename.endswith(".zip"):
39+
repo_ctx.download_and_extract(
40+
url = url,
41+
sha256 = sha256,
42+
output = output,
43+
stripPrefix = strip_prefix,
44+
type = "zip",
45+
)
46+
47+
else:
48+
repo_ctx.download_and_extract(
49+
url = url,
50+
sha256 = sha256,
51+
output = output,
52+
stripPrefix = strip_prefix,
53+
)
54+
55+
56+
3357
def _create_download_info(repo_ctx):
3458
if repo_ctx.attr.url and repo_ctx.attr.urls:
3559
fail("Either `url` or `urls` attribute must be set")
@@ -71,8 +95,8 @@ def _normalize_download_info(repo_ctx):
7195

7296
def _create_symlinks(repo_ctx, root, entries, substitutions={}, mapping={}):
7397
for entry in entries:
74-
entry_fmt = utils.substitude(entry, substitutions)
75-
src_entry_path = utils.substitude(paths.join(root, entry_fmt), mapping)
98+
entry_fmt = utils.substitute(entry, substitutions)
99+
src_entry_path = utils.substitute(paths.join(root, entry_fmt), mapping)
76100
dst_entry_path = entry_fmt
77101
repo_ctx.symlink(src_entry_path, dst_entry_path)
78102

dev/bazel/utils.bzl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def _filter_out(lst_to_filter, filter):
5454
def _add_prefix(prefix, lst):
5555
return [ prefix + str(x) for x in lst ]
5656

57-
def _substitude(string, substitutions={}):
57+
def _substitute(string, substitutions={}):
5858
string_fmt = string
5959
for key, value in substitutions.items():
6060
string_fmt = string_fmt.replace(key, value)
@@ -99,7 +99,7 @@ utils = struct(
9999
normalize_dict = _normalize_dict,
100100
filter_out = _filter_out,
101101
add_prefix = _add_prefix,
102-
substitude = _substitude,
102+
substitute = _substitute,
103103
match_substring = _match_substring,
104104
remove_substring = _remove_substring,
105105
warn = _warn,

0 commit comments

Comments
 (0)