Skip to content

Commit deaa97c

Browse files
committed
Add unittest for the fix
1 parent 8458b5e commit deaa97c

File tree

4 files changed

+241
-11
lines changed

4 files changed

+241
-11
lines changed

sycl/unittests/kernel-and-program/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
add_sycl_unittest(KernelAndProgramTests OBJECT
22
Cache.cpp
3+
MultipleDevsCache.cpp
34
KernelRelease.cpp
45
KernelInfo.cpp
56
DeviceInfo.cpp

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

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "detail/context_impl.hpp"
1313
#include "detail/kernel_program_cache.hpp"
1414
#include "detail/program_impl.hpp"
15+
#include "HelperKernelInfo.hpp"
1516
#include <CL/sycl.hpp>
1617
#include <helpers/CommonRedefinitions.hpp>
1718
#include <helpers/PiImage.hpp>
@@ -37,17 +38,6 @@ class TestKernel2 {
3738
__SYCL_INLINE_NAMESPACE(cl) {
3839
namespace sycl {
3940
namespace detail {
40-
struct MockKernelInfo {
41-
static constexpr unsigned getNumParams() { return 0; }
42-
static const kernel_param_desc_t &getParamDesc(int) {
43-
static kernel_param_desc_t Dummy;
44-
return Dummy;
45-
}
46-
static constexpr bool isESIMD() { return false; }
47-
static constexpr bool callsThisItem() { return false; }
48-
static constexpr bool callsAnyThisFreeFunction() { return false; }
49-
};
50-
5141
template <> struct KernelInfo<TestKernel> : public MockKernelInfo {
5242
static constexpr const char *getName() { return "TestKernel"; }
5343
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//==----------------------- HelperKernelInfo.hpp ---------------------------==//
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+
#pragma once
10+
11+
#include <CL/sycl.hpp>
12+
13+
__SYCL_INLINE_NAMESPACE(cl) {
14+
namespace sycl {
15+
namespace detail {
16+
struct MockKernelInfo {
17+
static constexpr unsigned getNumParams() { return 0; }
18+
static const kernel_param_desc_t &getParamDesc(int) {
19+
static kernel_param_desc_t Dummy;
20+
return Dummy;
21+
}
22+
static constexpr bool isESIMD() { return false; }
23+
static constexpr bool callsThisItem() { return false; }
24+
static constexpr bool callsAnyThisFreeFunction() { return false; }
25+
};
26+
27+
} // namespace detail
28+
} // namespace sycl
29+
} // __SYCL_INLINE_NAMESPACE(cl)
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
//==--- KPCache.cpp --- KernelProgramCache for multiple devices unit test --==//
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+
#define SYCL2020_DISABLE_DEPRECATION_WARNINGS
10+
11+
#include "HelperKernelInfo.hpp"
12+
#include "detail/kernel_bundle_impl.hpp"
13+
#include <CL/sycl.hpp>
14+
#include <helpers/CommonRedefinitions.hpp>
15+
#include <helpers/PiImage.hpp>
16+
#include <helpers/PiMock.hpp>
17+
18+
#include <gtest/gtest.h>
19+
20+
#include <iostream>
21+
22+
using namespace sycl;
23+
24+
class MultTestKernel {
25+
public:
26+
void operator()(cl::sycl::item<1>){};
27+
};
28+
29+
__SYCL_INLINE_NAMESPACE(cl) {
30+
namespace sycl {
31+
namespace detail {
32+
template <> struct KernelInfo<MultTestKernel> : public MockKernelInfo {
33+
static constexpr const char *getName() { return "MultTestKernel"; }
34+
};
35+
} // namespace detail
36+
} // namespace sycl
37+
} // __SYCL_INLINE_NAMESPACE(cl)
38+
39+
static sycl::unittest::PiImage generateDefaultImage() {
40+
using namespace sycl::unittest;
41+
42+
PiPropertySet PropSet;
43+
44+
std::vector<unsigned char> Bin{0, 1, 2, 3, 4, 5}; // Random data
45+
46+
PiArray<PiOffloadEntry> Entries = makeEmptyKernels({"MultTestKernel"});
47+
48+
PiImage Img{PI_DEVICE_BINARY_TYPE_SPIRV, // Format
49+
__SYCL_PI_DEVICE_BINARY_TARGET_SPIRV64, // DeviceTargetSpec
50+
"", // Compile options
51+
"", // Link options
52+
std::move(Bin),
53+
std::move(Entries),
54+
std::move(PropSet)};
55+
56+
return Img;
57+
}
58+
59+
static sycl::unittest::PiImage Img = generateDefaultImage();
60+
static sycl::unittest::PiImageArray<1> ImgArray{&Img};
61+
62+
static pi_result redefinedContextCreate(
63+
const pi_context_properties *properties, pi_uint32 num_devices,
64+
const pi_device *devices,
65+
void (*pfn_notify)(const char *errinfo, const void *private_info, size_t cb,
66+
void *user_data),
67+
void *user_data, pi_context *ret_context) {
68+
*ret_context = reinterpret_cast<pi_context>(123);
69+
return PI_SUCCESS;
70+
}
71+
72+
static pi_result redefinedContextRelease(pi_context context) {
73+
return PI_SUCCESS;
74+
}
75+
76+
static pi_result redefinedDevicesGet(pi_platform platform,
77+
pi_device_type device_type,
78+
pi_uint32 num_entries, pi_device *devices,
79+
pi_uint32 *num_devices) {
80+
if (num_devices) {
81+
*num_devices = static_cast<pi_uint32>(2);
82+
return PI_SUCCESS;
83+
}
84+
85+
devices[0] = reinterpret_cast<pi_device>(1111);
86+
devices[1] = reinterpret_cast<pi_device>(2222);
87+
return PI_SUCCESS;
88+
}
89+
90+
static pi_result redefinedDeviceGetInfo(pi_device device,
91+
pi_device_info param_name,
92+
size_t param_value_size,
93+
void *param_value,
94+
size_t *param_value_size_ret) {
95+
if (param_name == PI_DEVICE_INFO_TYPE) {
96+
auto *Result = reinterpret_cast<_pi_device_type *>(param_value);
97+
*Result = PI_DEVICE_TYPE_GPU;
98+
}
99+
return PI_SUCCESS;
100+
}
101+
102+
static pi_result redefinedDeviceRetain(pi_device device) { return PI_SUCCESS; }
103+
104+
static pi_result redefinedDeviceRelease(pi_device device) { return PI_SUCCESS; }
105+
106+
static pi_result redefinedQueueCreate(pi_context context, pi_device device,
107+
pi_queue_properties properties,
108+
pi_queue *queue) {
109+
*queue = reinterpret_cast<pi_queue>(1234);
110+
return PI_SUCCESS;
111+
}
112+
113+
static pi_result redefinedQueueRelease(pi_queue command_queue) {
114+
return PI_SUCCESS;
115+
}
116+
117+
static int ProgramNum = 12345;
118+
static pi_result redefinedProgramCreate(pi_context context, const void *il,
119+
size_t length,
120+
pi_program *res_program) {
121+
int CurrentProgram = ProgramNum;
122+
*res_program = reinterpret_cast<pi_program>(CurrentProgram);
123+
++ProgramNum;
124+
return PI_SUCCESS;
125+
}
126+
127+
static int RetainCounter = 0;
128+
static pi_result redefinedProgramRetain(pi_program program) {
129+
++RetainCounter;
130+
return PI_SUCCESS;
131+
}
132+
133+
static int KernelReleaseCounter = 0;
134+
static pi_result redefinedKernelRelease(pi_kernel kernel) {
135+
++KernelReleaseCounter;
136+
return PI_SUCCESS;
137+
}
138+
139+
class MultipleDeviceCacheTest : public ::testing::Test {
140+
public:
141+
MultipleDeviceCacheTest() : Plt{default_selector()} {}
142+
143+
protected:
144+
void SetUp() override {
145+
if (Plt.is_host() || Plt.get_backend() != backend::opencl) {
146+
std::clog << "This test is only supported on OpenCL devices\n";
147+
std::clog << "Current platform is "
148+
<< Plt.get_info<info::platform::name>();
149+
return;
150+
}
151+
152+
Mock = std::make_unique<unittest::PiMock>(Plt);
153+
154+
setupDefaultMockAPIs(*Mock);
155+
Mock->redefine<detail::PiApiKind::piDevicesGet>(redefinedDevicesGet);
156+
Mock->redefine<detail::PiApiKind::piDeviceGetInfo>(redefinedDeviceGetInfo);
157+
Mock->redefine<detail::PiApiKind::piDeviceRetain>(redefinedDeviceRetain);
158+
Mock->redefine<detail::PiApiKind::piDeviceRelease>(redefinedDeviceRelease);
159+
Mock->redefine<detail::PiApiKind::piContextCreate>(redefinedContextCreate);
160+
Mock->redefine<detail::PiApiKind::piContextRelease>(
161+
redefinedContextRelease);
162+
Mock->redefine<detail::PiApiKind::piQueueCreate>(redefinedQueueCreate);
163+
Mock->redefine<detail::PiApiKind::piQueueRelease>(redefinedQueueRelease);
164+
Mock->redefine<detail::PiApiKind::piProgramRetain>(redefinedProgramRetain);
165+
Mock->redefine<detail::PiApiKind::piProgramCreate>(redefinedProgramCreate);
166+
Mock->redefine<detail::PiApiKind::piKernelRelease>(redefinedKernelRelease);
167+
}
168+
169+
protected:
170+
std::unique_ptr<unittest::PiMock> Mock;
171+
platform Plt;
172+
};
173+
174+
// Test that program is retained for each device
175+
TEST_F(MultipleDeviceCacheTest, ProgramRetain) {
176+
if (Plt.is_host()) {
177+
return;
178+
}
179+
180+
std::vector<sycl::device> Devices = Plt.get_devices(info::device_type::gpu);
181+
sycl::context Context(Devices);
182+
sycl::queue Queue(Context, Devices[0]);
183+
assert(Devices.size() == 2);
184+
185+
auto Bundle = cl::sycl::get_kernel_bundle<sycl::bundle_state::input>(
186+
Queue.get_context());
187+
188+
Queue.submit([&](cl::sycl::handler &cgh) {
189+
cgh.parallel_for<MultTestKernel>(cl::sycl::nd_range<1>(10, 10),
190+
MultTestKernel{});
191+
});
192+
193+
auto BundleObject = cl::sycl::build(Bundle, Bundle.get_devices());
194+
auto KernelID = cl::sycl::get_kernel_id<MultTestKernel>();
195+
auto Kernel = BundleObject.get_kernel(KernelID);
196+
auto BundleImpl = getSyclObjImpl(Bundle);
197+
int NumRetains = BundleImpl->size() * 2;
198+
199+
EXPECT_EQ(RetainCounter, NumRetains)
200+
<< "Expect " << NumRetains << " piProgramRetain calls";
201+
}
202+
203+
// Test that each kernel released only 1 time in ~KernelProgramCache()
204+
TEST_F(MultipleDeviceCacheTest, KernelRelease) {
205+
platform Plt{default_selector()};
206+
if (Plt.is_host()) {
207+
return;
208+
}
209+
EXPECT_EQ(KernelReleaseCounter, 3) << "Expect 3 piKernelRelease calls";
210+
}

0 commit comments

Comments
 (0)