Skip to content

Commit b45a7bb

Browse files
committed
[SYCL] Remove linking workaround and test SYCL interlinking
This commit removes a workaround for linking inline SYCL code with SYCLBIN. Additionally, it relaxes the requirement for dependency resolution when device images are looked up for anything other than executable state, avoiding errors when the symbol resolution is done manually. Signed-off-by: Larsen, Steffen <[email protected]>
1 parent 642a6eb commit b45a7bb

File tree

8 files changed

+154
-45
lines changed

8 files changed

+154
-45
lines changed

sycl/source/detail/kernel_bundle_impl.hpp

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -245,26 +245,6 @@ class kernel_bundle_impl
245245
// TODO: Unify with c'tor for sycl::compile and sycl::build by calling
246246
// sycl::join on vector of kernel_bundles
247247

248-
// Due to a bug in L0, specializations with conflicting IDs will overwrite
249-
// each other when linked together, so to avoid this issue we link
250-
// regular offline-compiled SYCL device images in separation.
251-
// TODO: Remove when spec const overwriting issue has been fixed in L0.
252-
std::vector<const DevImgPlainWithDeps *> OfflineDeviceImages;
253-
std::unordered_set<std::shared_ptr<device_image_impl>>
254-
OfflineDeviceImageSet;
255-
for (const kernel_bundle<bundle_state::object> &ObjectBundle :
256-
ObjectBundles) {
257-
for (const DevImgPlainWithDeps &DeviceImageWithDeps :
258-
getSyclObjImpl(ObjectBundle)->MDeviceImages) {
259-
if (getSyclObjImpl(DeviceImageWithDeps.getMain())->getOriginMask() &
260-
ImageOriginSYCLOffline) {
261-
OfflineDeviceImages.push_back(&DeviceImageWithDeps);
262-
for (const device_image_plain &DevImg : DeviceImageWithDeps)
263-
OfflineDeviceImageSet.insert(getSyclObjImpl(DevImg));
264-
}
265-
}
266-
}
267-
268248
// Collect all unique images.
269249
std::vector<device_image_plain> DevImages;
270250
{
@@ -273,9 +253,7 @@ class kernel_bundle_impl
273253
ObjectBundles)
274254
for (const device_image_plain &DevImg :
275255
getSyclObjImpl(ObjectBundle)->MUniqueDeviceImages)
276-
if (OfflineDeviceImageSet.find(getSyclObjImpl(DevImg)) ==
277-
OfflineDeviceImageSet.end())
278-
DevImagesSet.insert(getSyclObjImpl(DevImg));
256+
DevImagesSet.insert(getSyclObjImpl(DevImg));
279257
DevImages.reserve(DevImagesSet.size());
280258
for (auto It = DevImagesSet.begin(); It != DevImagesSet.end();)
281259
DevImages.push_back(createSyclObjFromImpl<device_image_plain>(
@@ -390,25 +368,6 @@ class kernel_bundle_impl
390368
// added.
391369
}
392370

393-
// ... And link the offline images in separation. (Workaround.)
394-
for (const DevImgPlainWithDeps *DeviceImageWithDeps : OfflineDeviceImages) {
395-
// Skip images which are not compatible with devices provided
396-
if (std::none_of(MDevices.begin(), MDevices.end(),
397-
[DeviceImageWithDeps](const device &Dev) {
398-
return getSyclObjImpl(DeviceImageWithDeps->getMain())
399-
->compatible_with_device(Dev);
400-
}))
401-
continue;
402-
403-
std::vector<device_image_plain> LinkedResults =
404-
detail::ProgramManager::getInstance().link(
405-
DeviceImageWithDeps->getAll(), MDevices, PropList);
406-
MDeviceImages.insert(MDeviceImages.end(), LinkedResults.begin(),
407-
LinkedResults.end());
408-
MUniqueDeviceImages.insert(MUniqueDeviceImages.end(),
409-
LinkedResults.begin(), LinkedResults.end());
410-
}
411-
412371
removeDuplicateImages();
413372

414373
for (const kernel_bundle<bundle_state::object> &Bundle : ObjectBundles) {

sycl/source/detail/program_manager/program_manager.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2599,7 +2599,10 @@ ProgramManager::getSYCLDeviceImagesWithCompatibleState(
25992599
std::lock_guard<std::mutex> KernelIDsGuard(m_KernelIDsMutex);
26002600
ImgInfo.KernelIDs = m_BinImg2KernelIDs[BinImage];
26012601
}
2602-
ImgInfo.Deps = collectDeviceImageDeps(*BinImage, {DevImpl});
2602+
ImgInfo.Deps =
2603+
collectDeviceImageDeps(*BinImage, {DevImpl},
2604+
/*ErrorOnUnresolvableImport=*/TargetState ==
2605+
bundle_state::executable);
26032606
}
26042607
const bundle_state ImgState = ImgInfo.State;
26052608
const std::shared_ptr<std::vector<sycl::kernel_id>> &ImageKernelIDs =
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <sycl/sycl.hpp>
2+
3+
namespace syclext = sycl::ext::oneapi;
4+
namespace syclexp = sycl::ext::oneapi::experimental;
5+
6+
typedef void (*FuncPtrT)(size_t *);
7+
8+
struct ArgsT {
9+
size_t *Ptr;
10+
FuncPtrT *FuncPtr;
11+
};
12+
13+
SYCL_EXTERNAL size_t GetID() {
14+
return syclext::this_work_item::get_nd_item<1>().get_global_id();
15+
}
16+
17+
extern "C" SYCL_EXTERNAL SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(
18+
(syclexp::nd_range_kernel<1>)) void Kernel(ArgsT Args) {
19+
(**Args.FuncPtr)(Args.Ptr);
20+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#include "common.hpp"
2+
3+
#include <sycl/usm.hpp>
4+
5+
namespace syclexp = sycl::ext::oneapi::experimental;
6+
7+
typedef void (*FuncPtrT)(size_t *);
8+
9+
struct ArgsT {
10+
size_t *Ptr;
11+
FuncPtrT *FuncPtr;
12+
};
13+
14+
#ifdef __SYCL_DEVICE_ONLY__
15+
SYCL_EXTERNAL size_t GetID();
16+
#else
17+
// Host-side code to avoid linker problems. Will never be called.
18+
SYCL_EXTERNAL size_t GetID() { return 0; }
19+
#endif
20+
21+
SYCL_EXTERNAL
22+
void Func(size_t *Ptr) {
23+
size_t GlobalID = GetID();
24+
Ptr[GlobalID] = GlobalID;
25+
}
26+
27+
SYCL_EXT_ONEAPI_FUNCTION_PROPERTY((syclexp::single_task_kernel))
28+
void GetFuncPtr(ArgsT Args) { *Args.FuncPtr = Func; }
29+
30+
constexpr size_t N = 32;
31+
32+
int main(int argc, char *argv[]) {
33+
assert(argc == 2);
34+
35+
sycl::queue Q;
36+
37+
int Failed = CommonLoadCheck(Q.get_context(), argv[1]);
38+
39+
#if defined(SYCLBIN_INPUT_STATE)
40+
auto SYCLBINInput = syclexp::get_kernel_bundle<sycl::bundle_state::input>(
41+
Q.get_context(), std::string{argv[1]});
42+
auto SYCLBINObj = sycl::compile(SYCLBINInput);
43+
#elif defined(SYCLBIN_OBJECT_STATE)
44+
auto SYCLBINObj = syclexp::get_kernel_bundle<sycl::bundle_state::object>(
45+
Q.get_context(), std::string{argv[1]});
46+
#else // defined(SYCLBIN_EXECUTABLE_STATE)
47+
#error "Test does not work with executable state."
48+
#endif
49+
50+
auto KBObj =
51+
syclexp::get_kernel_bundle<GetFuncPtr, sycl::bundle_state::object>(
52+
Q.get_context());
53+
auto KBExe = sycl::link({KBObj, SYCLBINObj});
54+
55+
ArgsT Args{};
56+
Args.FuncPtr = sycl::malloc_shared<FuncPtrT>(N, Q);
57+
Args.Ptr = sycl::malloc_shared<size_t>(N, Q);
58+
59+
sycl::kernel GetFuncPtrKern = KBExe.ext_oneapi_get_kernel<GetFuncPtr>();
60+
Q.submit([&](sycl::handler &CGH) {
61+
CGH.set_args(Args);
62+
CGH.single_task(GetFuncPtrKern);
63+
}).wait();
64+
65+
sycl::kernel Kern = KBExe.ext_oneapi_get_kernel("Kernel");
66+
Q.submit([&](sycl::handler &CGH) {
67+
CGH.set_args(Args);
68+
CGH.parallel_for(sycl::nd_range{{N}, {N}}, Kern);
69+
}).wait();
70+
71+
for (size_t I = 0; I < N; ++I) {
72+
if (Args.Ptr[I] != I) {
73+
std::cout << Args.Ptr[I] << " != " << I << std::endl;
74+
++Failed;
75+
}
76+
}
77+
78+
return Failed;
79+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//==-------- link_sycl_inline_input.cpp --- SYCLBIN extension tests --------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// REQUIRES: aspect-usm_shared_allocations
10+
11+
// -- Test for linking between inline SYCL code and SYCLBIN code.
12+
13+
// Due to the regression in https://github.com/intel/llvm/issues/18432 it will
14+
// fail to build the SYCLBIN with nvptx targets. Once this is fixed,
15+
// %{sycl_target_opts} should be added to the SYCLBIN generation run-line.
16+
// REQUIRES: target-spir
17+
18+
// RUN: %clangxx --offload-new-driver -fsyclbin=input -fsycl-allow-device-image-dependencies -Xclang -fsycl-allow-func-ptr %S/Inputs/link_sycl_inline.cpp -o %t.syclbin
19+
// RUN: %{build} -fsycl-allow-device-image-dependencies -o %t.out
20+
// RUN: %{l0_leak_check} %{run} %t.out %t.syclbin
21+
22+
#define SYCLBIN_INPUT_STATE
23+
24+
#include "Inputs/link_sycl_inline.hpp"
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//==-------- link_sycl_inline_object.cpp --- SYCLBIN extension tests --------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// REQUIRES: aspect-usm_shared_allocations
10+
11+
// -- Test for linking between inline SYCL code and SYCLBIN code.
12+
13+
// Due to the regression in https://github.com/intel/llvm/issues/18432 it will
14+
// fail to build the SYCLBIN with nvptx targets. Once this is fixed,
15+
// %{sycl_target_opts} should be added to the SYCLBIN generation run-line.
16+
// REQUIRES: target-spir
17+
18+
// RUN: %clangxx --offload-new-driver -fsyclbin=object -fsycl-allow-device-image-dependencies -Xclang -fsycl-allow-func-ptr %S/Inputs/link_sycl_inline.cpp -o %t.syclbin
19+
// RUN: %{build} -fsycl-allow-device-image-dependencies -o %t.out
20+
// RUN: %{l0_leak_check} %{run} %t.out %t.syclbin
21+
22+
#define SYCLBIN_OBJECT_STATE
23+
24+
#include "Inputs/link_sycl_inline.hpp"

sycl/test/e2e_test_requirements/no_sycl_hpp_in_e2e_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// CHECK-DAG: README.md
77
// CHECK-DAG: lit.cfg.py
88
//
9-
// CHECK-NUM-MATCHES: 25
9+
// CHECK-NUM-MATCHES: 26
1010
//
1111
// This test verifies that `<sycl/sycl.hpp>` isn't used in E2E tests. Instead,
1212
// fine-grained includes should used, see

sycl/unittests/kernel-and-program/OutOfResources.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ TEST_P(OutOfResourcesTestSuite, urProgramLink) {
174174
auto b3 = sycl::link({b1, b2});
175175
EXPECT_FALSE(outOfResourcesToggle);
176176
// one restart due to out of resources, one link per each of b1 and b2.
177-
EXPECT_EQ(nProgramLink, 3);
177+
EXPECT_EQ(nProgramLink, 2);
178178
// no programs should be in the cache due to out of resources.
179179
{
180180
detail::KernelProgramCache::ProgramCache &Cache =

0 commit comments

Comments
 (0)