Skip to content

Commit 008519a

Browse files
author
Alexander Batashev
authored
[SYCL] Emit program build logs for warning levels >= 2 (#5319)
When `SYCL_RT_WARNING_LEVEL` is set to 2 or higher, a program build log will be printed to `std::clog`.
1 parent 96d2e17 commit 008519a

File tree

8 files changed

+221
-6
lines changed

8 files changed

+221
-6
lines changed

sycl/source/detail/config.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,4 @@ CONFIG(SYCL_CACHE_MAX_DEVICE_IMAGE_SIZE, 16, __SYCL_CACHE_MAX_DEVICE_IMAGE_SIZE)
3737
CONFIG(INTEL_ENABLE_OFFLOAD_ANNOTATIONS, 1, __SYCL_INTEL_ENABLE_OFFLOAD_ANNOTATIONS)
3838
CONFIG(SYCL_ENABLE_DEFAULT_CONTEXTS, 1, __SYCL_ENABLE_DEFAULT_CONTEXTS)
3939
CONFIG(SYCL_QUEUE_THREAD_POOL_SIZE, 4, __SYCL_QUEUE_THREAD_POOL_SIZE)
40+
CONFIG(SYCL_RT_WARNING_LEVEL, 4, __SYCL_RT_WARNING_LEVEL)

sycl/source/detail/config.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,30 @@ template <> class SYCLConfig<SYCL_PI_TRACE> {
183183
}
184184
};
185185

186+
template <> class SYCLConfig<SYCL_RT_WARNING_LEVEL> {
187+
using BaseT = SYCLConfigBase<SYCL_RT_WARNING_LEVEL>;
188+
189+
public:
190+
static unsigned int get() { return getCachedValue(); }
191+
192+
static void reset() { (void)getCachedValue(true); }
193+
194+
private:
195+
static unsigned int getCachedValue(bool ResetCache = false) {
196+
const auto Parser = []() {
197+
const char *ValStr = BaseT::getRawValue();
198+
int SignedLevel = ValStr ? std::atoi(ValStr) : 0;
199+
return SignedLevel >= 0 ? SignedLevel : 0;
200+
};
201+
202+
static unsigned int Level = Parser();
203+
if (ResetCache)
204+
Level = Parser();
205+
206+
return Level;
207+
}
208+
};
209+
186210
template <> class SYCLConfig<SYCL_PARALLEL_FOR_RANGE_ROUNDING_TRACE> {
187211
using BaseT = SYCLConfigBase<SYCL_PARALLEL_FOR_RANGE_ROUNDING_TRACE>;
188212

sycl/source/detail/kernel_program_cache.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,15 @@ class KernelProgramCache {
130130
MKernelFastCache.emplace(CacheKey, CacheVal);
131131
}
132132

133+
/// Clears cache state.
134+
///
135+
/// This member function should only be used in unit tests.
136+
void reset() {
137+
MCachedPrograms = ProgramCacheT{};
138+
MKernelsPerProgramCache = KernelCacheT{};
139+
MKernelFastCache = KernelFastCacheT{};
140+
}
141+
133142
private:
134143
std::mutex MProgramCacheMutex;
135144
std::mutex MKernelsPerProgramCacheMutex;

sycl/source/detail/program_manager/program_manager.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,17 @@ std::pair<RT::PiProgram, bool> ProgramManager::getOrCreatePIProgram(
438438
return {NativePrg, BinProg.size()};
439439
}
440440

441+
/// Emits information about built programs if the appropriate contitions are
442+
/// met, namely when SYCL_RT_WARNING_LEVEL is greater than or equal to 2.
443+
static void emitBuiltProgramInfo(const pi_program &Prog,
444+
const ContextImplPtr &Context) {
445+
if (SYCLConfig<SYCL_RT_WARNING_LEVEL>::get() >= 2) {
446+
std::string ProgramBuildLog =
447+
ProgramManager::getProgramBuildLog(Prog, Context);
448+
std::clog << ProgramBuildLog << std::endl;
449+
}
450+
}
451+
441452
RT::PiProgram ProgramManager::getBuiltPIProgram(
442453
OSModuleHandle M, const ContextImplPtr &ContextImpl,
443454
const DeviceImplPtr &DeviceImpl, const std::string &KernelName,
@@ -511,6 +522,8 @@ RT::PiProgram ProgramManager::getBuiltPIProgram(
511522
getRawSyclObjImpl(Device)->getHandleRef(),
512523
ContextImpl->getCachedLibPrograms(), DeviceLibReqMask);
513524

525+
emitBuiltProgramInfo(BuiltProgram.get(), ContextImpl);
526+
514527
{
515528
std::lock_guard<std::mutex> Lock(MNativeProgramsMutex);
516529
NativePrograms[BuiltProgram.get()] = &Img;
@@ -1789,6 +1802,8 @@ device_image_plain ProgramManager::build(const device_image_plain &DeviceImage,
17891802
getRawSyclObjImpl(Devs[0])->getHandleRef(),
17901803
ContextImpl->getCachedLibPrograms(), DeviceLibReqMask);
17911804

1805+
emitBuiltProgramInfo(BuiltProgram.get(), ContextImpl);
1806+
17921807
{
17931808
std::lock_guard<std::mutex> Lock(MNativeProgramsMutex);
17941809
NativePrograms[BuiltProgram.get()] = &Img;

sycl/unittests/helpers/CommonRedefinitions.hpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,31 @@ inline pi_result redefinedProgramGetInfoCommon(pi_program program,
5353
size_t param_value_size,
5454
void *param_value,
5555
size_t *param_value_size_ret) {
56+
if (param_value_size_ret) {
57+
*param_value_size_ret = sizeof(size_t);
58+
}
5659
if (param_name == PI_PROGRAM_INFO_NUM_DEVICES) {
57-
auto value = reinterpret_cast<unsigned int *>(param_value);
58-
*value = 1;
60+
if (param_value) {
61+
auto value = reinterpret_cast<unsigned int *>(param_value);
62+
*value = 1;
63+
}
5964
}
6065

6166
if (param_name == PI_PROGRAM_INFO_BINARY_SIZES) {
62-
auto value = reinterpret_cast<size_t *>(param_value);
63-
value[0] = 1;
67+
if (param_value) {
68+
auto value = reinterpret_cast<size_t *>(param_value);
69+
value[0] = 1;
70+
}
6471
}
6572

6673
if (param_name == PI_PROGRAM_INFO_BINARIES) {
67-
auto value = reinterpret_cast<unsigned char *>(param_value);
68-
value[0] = 1;
74+
if (param_value_size_ret) {
75+
*param_value_size_ret = sizeof(unsigned char);
76+
}
77+
if (param_value) {
78+
auto value = reinterpret_cast<unsigned char *>(param_value);
79+
value[0] = 1;
80+
}
6981
}
7082

7183
return PI_SUCCESS;

sycl/unittests/helpers/ScopedEnvVar.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
#pragma once
1010

11+
#include <CL/sycl/detail/common.hpp>
12+
13+
#include <cstdlib>
1114
#include <functional>
1215
#include <stdlib.h>
1316

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
//==----------------- BuildLog.cpp --- Build log 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+
#include "gtest/internal/gtest-internal.h"
10+
#define SYCL2020_DISABLE_DEPRECATION_WARNINGS
11+
12+
#include <CL/sycl.hpp>
13+
#include <detail/config.hpp>
14+
#include <detail/context_impl.hpp>
15+
#include <detail/program_manager/program_manager.hpp>
16+
#include <helpers/CommonRedefinitions.hpp>
17+
#include <helpers/PiImage.hpp>
18+
#include <helpers/PiMock.hpp>
19+
#include <helpers/ScopedEnvVar.hpp>
20+
21+
#include <gtest/gtest.h>
22+
23+
#include <cstring>
24+
#include <stdlib.h>
25+
26+
#include <helpers/TestKernel.hpp>
27+
28+
// Same as defined in config.def
29+
static constexpr auto WarningLevelEnvVar = "SYCL_RT_WARNING_LEVEL";
30+
31+
static bool LogRequested = false;
32+
33+
static pi_result redefinedProgramGetBuildInfo(
34+
pi_program program, pi_device device, cl_program_build_info param_name,
35+
size_t param_value_size, void *param_value, size_t *param_value_size_ret) {
36+
37+
if (param_value_size_ret) {
38+
*param_value_size_ret = 1;
39+
}
40+
if (param_value) {
41+
*static_cast<char *>(param_value) = '1';
42+
}
43+
44+
if (param_name == PI_PROGRAM_BUILD_INFO_LOG) {
45+
LogRequested = true;
46+
}
47+
48+
return PI_SUCCESS;
49+
}
50+
51+
static pi_result redefinedDeviceGetInfo(pi_device device,
52+
pi_device_info param_name,
53+
size_t param_value_size,
54+
void *param_value,
55+
size_t *param_value_size_ret) {
56+
if (param_name == PI_DEVICE_INFO_NAME) {
57+
const std::string name = "Test Device";
58+
if (param_value_size_ret) {
59+
*param_value_size_ret = name.size();
60+
}
61+
if (param_value) {
62+
auto *val = static_cast<char *>(param_value);
63+
strcpy(val, name.data());
64+
}
65+
}
66+
if (param_name == PI_DEVICE_INFO_COMPILER_AVAILABLE) {
67+
if (param_value_size_ret) {
68+
*param_value_size_ret = sizeof(cl_bool);
69+
}
70+
if (param_value) {
71+
auto *val = static_cast<cl_bool *>(param_value);
72+
*val = 1;
73+
}
74+
}
75+
return PI_SUCCESS;
76+
}
77+
78+
static void setupCommonTestAPIs(sycl::unittest::PiMock &Mock) {
79+
using namespace sycl::detail;
80+
Mock.redefine<PiApiKind::piProgramGetBuildInfo>(redefinedProgramGetBuildInfo);
81+
Mock.redefine<PiApiKind::piDeviceGetInfo>(redefinedDeviceGetInfo);
82+
}
83+
84+
TEST(BuildLog, OutputNothingOnLevel1) {
85+
using namespace sycl::detail;
86+
using namespace sycl::unittest;
87+
ScopedEnvVar var(WarningLevelEnvVar, "1",
88+
SYCLConfig<SYCL_RT_WARNING_LEVEL>::reset);
89+
90+
sycl::platform Plt{sycl::default_selector()};
91+
// TODO make sure unsupported platform is never selected
92+
if (Plt.is_host() || Plt.get_backend() == sycl::backend::ext_oneapi_cuda ||
93+
Plt.get_backend() == sycl::backend::ext_oneapi_hip) {
94+
GTEST_SKIP_("Test is not supported on this platform");
95+
}
96+
97+
sycl::unittest::PiMock Mock{Plt};
98+
setupDefaultMockAPIs(Mock);
99+
setupCommonTestAPIs(Mock);
100+
101+
const sycl::device Dev = Plt.get_devices()[0];
102+
103+
sycl::queue Queue{Dev};
104+
105+
sycl::context Ctx = Queue.get_context();
106+
auto ContextImpl = getSyclObjImpl(Ctx);
107+
// Make sure no kernels are cached
108+
ContextImpl->getKernelProgramCache().reset();
109+
110+
LogRequested = false;
111+
sycl::kernel_bundle KernelBundle =
112+
sycl::get_kernel_bundle<sycl::bundle_state::input>(Ctx, {Dev});
113+
(void)sycl::build(KernelBundle);
114+
115+
EXPECT_EQ(LogRequested, false);
116+
}
117+
118+
TEST(BuildLog, OutputLogOnLevel2) {
119+
using namespace sycl::detail;
120+
using namespace sycl::unittest;
121+
ScopedEnvVar var(WarningLevelEnvVar, "2",
122+
SYCLConfig<SYCL_RT_WARNING_LEVEL>::reset);
123+
124+
sycl::platform Plt{sycl::default_selector()};
125+
// TODO make sure unsupported platform is never selected
126+
if (Plt.is_host() || Plt.get_backend() == sycl::backend::ext_oneapi_cuda ||
127+
Plt.get_backend() == sycl::backend::ext_oneapi_hip) {
128+
GTEST_SKIP_("Test is not supported on this platform");
129+
}
130+
131+
sycl::unittest::PiMock Mock{Plt};
132+
setupDefaultMockAPIs(Mock);
133+
setupCommonTestAPIs(Mock);
134+
135+
const sycl::device Dev = Plt.get_devices()[0];
136+
137+
sycl::queue Queue{Dev};
138+
139+
const sycl::context Ctx = Queue.get_context();
140+
auto ContextImpl = getSyclObjImpl(Ctx);
141+
// Make sure no kernels are cached
142+
ContextImpl->getKernelProgramCache().reset();
143+
144+
LogRequested = false;
145+
sycl::kernel_bundle KernelBundle =
146+
sycl::get_kernel_bundle<sycl::bundle_state::input>(Ctx, {Dev});
147+
(void)sycl::build(KernelBundle);
148+
149+
EXPECT_EQ(LogRequested, true);
150+
}

sycl/unittests/program_manager/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
set(CMAKE_CXX_EXTENSIONS OFF)
22

33
add_sycl_unittest(ProgramManagerTests OBJECT
4+
BuildLog.cpp
45
EliminatedArgMask.cpp
56
itt_annotations.cpp
67
)

0 commit comments

Comments
 (0)