DPC++ Runtime
Runtime libraries for oneAPI Data Parallel C++
common.hpp
Go to the documentation of this file.
1 //==---------- common.hpp ----- Common declarations ------------------------==//
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/detail/cl.h>
16 
17 #include <cstdint>
18 #include <string>
19 
20 // Default signature enables the passing of user code location information to
21 // public methods as a default argument. If the end-user wants to disable the
22 // code location information, they must compile the code with
23 // -DDISABLE_SYCL_INSTRUMENTATION_METADATA flag
25 namespace sycl {
26 namespace detail {
27 // Data structure that captures the user code location information using the
28 // builtin capabilities of the compiler
29 struct code_location {
30 #ifdef _MSC_VER
31  // Since MSVC does not support the required builtins, we
32  // implement the version with "unknown"s which is handled
33  // correctly by the instrumentation
34  static constexpr code_location current(const char *fileName = nullptr,
35  const char *funcName = nullptr,
36  unsigned long lineNo = 0,
37  unsigned long columnNo = 0) noexcept {
38  return code_location(fileName, funcName, lineNo, columnNo);
39  }
40 #else
41  // FIXME Having a nullptr for fileName here is a short-term solution to
42  // workaround leak of full paths in builds
43  static constexpr code_location
44  current(const char *fileName = nullptr,
45  const char *funcName = __builtin_FUNCTION(),
46  unsigned long lineNo = __builtin_LINE(),
47  unsigned long columnNo = 0) noexcept {
48  return code_location(fileName, funcName, lineNo, columnNo);
49  }
50 #endif
51 
52  constexpr code_location(const char *file, const char *func, int line,
53  int col) noexcept
54  : MFileName(file), MFunctionName(func), MLineNo(line), MColumnNo(col) {}
55 
56  constexpr code_location() noexcept
57  : MFileName(nullptr), MFunctionName(nullptr), MLineNo(0), MColumnNo(0) {}
58 
59  constexpr unsigned long lineNumber() const noexcept { return MLineNo; }
60  constexpr unsigned long columnNumber() const noexcept { return MColumnNo; }
61  constexpr const char *fileName() const noexcept { return MFileName; }
62  constexpr const char *functionName() const noexcept { return MFunctionName; }
63 
64 private:
65  const char *MFileName;
66  const char *MFunctionName;
67  unsigned long MLineNo;
68  unsigned long MColumnNo;
69 };
70 } // namespace detail
71 } // namespace sycl
72 } // __SYCL_INLINE_NAMESPACE(cl)
73 
75 namespace sycl {
76 namespace detail {
77 
78 __SYCL_EXPORT const char *stringifyErrorCode(cl_int error);
79 
80 static inline std::string codeToString(cl_int code) {
81  return std::string(std::to_string(code) + " (" + stringifyErrorCode(code) +
82  ")");
83 }
84 
85 } // namespace detail
86 } // namespace sycl
87 } // __SYCL_INLINE_NAMESPACE(cl)
88 
89 #ifdef __SYCL_DEVICE_ONLY__
90 // TODO remove this when 'assert' is supported in device code
91 #define __SYCL_ASSERT(x)
92 #else
93 #define __SYCL_ASSERT(x) assert(x)
94 #endif // #ifdef __SYCL_DEVICE_ONLY__
95 
96 #define __SYCL_OCL_ERROR_REPORT \
97  "Native API failed. " /*__FILE__*/ \
98  /* TODO: replace __FILE__ to report only relative path*/ \
99  /* ":" __SYCL_STRINGIFY(__LINE__) ": " */ \
100  "Native API returns: "
101 
102 #ifndef __SYCL_SUPPRESS_OCL_ERROR_REPORT
103 #include <iostream>
104 // TODO: rename all names with direct use of OCL/OPENCL to be backend agnostic.
105 #define __SYCL_REPORT_OCL_ERR_TO_STREAM(expr) \
106  { \
107  auto code = expr; \
108  if (code != CL_SUCCESS) { \
109  std::cerr << __SYCL_OCL_ERROR_REPORT \
110  << cl::sycl::detail::codeToString(code) << std::endl; \
111  } \
112  }
113 #endif
114 
115 #ifndef SYCL_SUPPRESS_EXCEPTIONS
116 #include <CL/sycl/exception.hpp>
117 
118 #define __SYCL_REPORT_OCL_ERR_TO_EXC(expr, exc) \
119  { \
120  auto code = expr; \
121  if (code != CL_SUCCESS) { \
122  throw exc(__SYCL_OCL_ERROR_REPORT + \
123  cl::sycl::detail::codeToString(code), \
124  code); \
125  } \
126  }
127 #define __SYCL_REPORT_OCL_ERR_TO_EXC_THROW(code, exc) \
128  __SYCL_REPORT_OCL_ERR_TO_EXC(code, exc)
129 #define __SYCL_REPORT_OCL_ERR_TO_EXC_BASE(code) \
130  __SYCL_REPORT_OCL_ERR_TO_EXC(code, cl::sycl::runtime_error)
131 #else
132 #define __SYCL_REPORT_OCL_ERR_TO_EXC_BASE(code) \
133  __SYCL_REPORT_OCL_ERR_TO_STREAM(code)
134 #endif
135 
136 #ifdef __SYCL_SUPPRESS_OCL_ERROR_REPORT
137 #define __SYCL_CHECK_OCL_CODE(X) (void)(X)
138 #define __SYCL_CHECK_OCL_CODE_THROW(X, EXC) (void)(X)
139 #define __SYCL_CHECK_OCL_CODE_NO_EXC(X) (void)(X)
140 #else
141 #define __SYCL_CHECK_OCL_CODE(X) __SYCL_REPORT_OCL_ERR_TO_EXC_BASE(X)
142 #define __SYCL_CHECK_OCL_CODE_THROW(X, EXC) \
143  __SYCL_REPORT_OCL_ERR_TO_EXC_THROW(X, EXC)
144 #define __SYCL_CHECK_OCL_CODE_NO_EXC(X) __SYCL_REPORT_OCL_ERR_TO_STREAM(X)
145 #endif
146 
148 namespace sycl {
149 namespace detail {
150 
151 // Helper function for extracting implementation from SYCL's interface objects.
152 // Note! This function relies on the fact that all SYCL interface classes
153 // contain "impl" field that points to implementation object. "impl" field
154 // should be accessible from this function.
155 //
156 // Note that due to a bug in MSVC compilers (including MSVC2019 v19.20), it
157 // may not recognize the usage of this function in friend member declarations
158 // if the template parameter name there is not equal to the name used here,
159 // i.e. 'Obj'. For example, using 'Obj' here and 'T' in such declaration
160 // would trigger that error in MSVC:
161 // template <class T>
162 // friend decltype(T::impl) detail::getSyclObjImpl(const T &SyclObject);
163 template <class Obj> decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject) {
164  return SyclObject.impl;
165 }
166 
167 // Returns the raw pointer to the impl object of given face object. The caller
168 // must make sure the returned pointer is not captured in a field or otherwise
169 // stored - i.e. must live only as on-stack value.
170 template <class T>
171 typename detail::add_pointer_t<typename decltype(T::impl)::element_type>
172 getRawSyclObjImpl(const T &SyclObject) {
173  return SyclObject.impl.get();
174 }
175 
176 // Helper function for creation SYCL interface objects from implementations.
177 // Note! This function relies on the fact that all SYCL interface classes
178 // contain "impl" field that points to implementation object. "impl" field
179 // should be accessible from this function.
180 template <class T> T createSyclObjFromImpl(decltype(T::impl) ImplObj) {
181  return T(ImplObj);
182 }
183 
184 // Produces N-dimensional object of type T whose all components are initialized
185 // to given integer value.
186 template <int N, template <int> class T> struct InitializedVal {
187  template <int Val> static T<N> get();
188 };
189 
190 // Specialization for a one-dimensional type.
191 template <template <int> class T> struct InitializedVal<1, T> {
192  template <int Val> static T<1> get() { return T<1>{Val}; }
193 };
194 
195 // Specialization for a two-dimensional type.
196 template <template <int> class T> struct InitializedVal<2, T> {
197  template <int Val> static T<2> get() { return T<2>{Val, Val}; }
198 };
199 
200 // Specialization for a three-dimensional type.
201 template <template <int> class T> struct InitializedVal<3, T> {
202  template <int Val> static T<3> get() { return T<3>{Val, Val, Val}; }
203 };
204 
206 template <int NDIMS, int DIM, template <int> class LoopBoundTy, typename FuncTy,
207  template <int> class LoopIndexTy>
209  NDLoopIterateImpl(const LoopIndexTy<NDIMS> &LowerBound,
210  const LoopBoundTy<NDIMS> &Stride,
211  const LoopBoundTy<NDIMS> &UpperBound, FuncTy f,
212  LoopIndexTy<NDIMS> &Index) {
213  constexpr size_t AdjIdx = NDIMS - 1 - DIM;
214  for (Index[AdjIdx] = LowerBound[AdjIdx]; Index[AdjIdx] < UpperBound[AdjIdx];
215  Index[AdjIdx] += Stride[AdjIdx]) {
216 
217  NDLoopIterateImpl<NDIMS, DIM - 1, LoopBoundTy, FuncTy, LoopIndexTy>{
218  LowerBound, Stride, UpperBound, f, Index};
219  }
220  }
221 };
222 
223 // Specialization for DIM=0 to terminate recursion
224 template <int NDIMS, template <int> class LoopBoundTy, typename FuncTy,
225  template <int> class LoopIndexTy>
226 struct NDLoopIterateImpl<NDIMS, 0, LoopBoundTy, FuncTy, LoopIndexTy> {
227  NDLoopIterateImpl(const LoopIndexTy<NDIMS> &LowerBound,
228  const LoopBoundTy<NDIMS> &Stride,
229  const LoopBoundTy<NDIMS> &UpperBound, FuncTy f,
230  LoopIndexTy<NDIMS> &Index) {
231 
232  constexpr size_t AdjIdx = NDIMS - 1;
233  for (Index[AdjIdx] = LowerBound[AdjIdx]; Index[AdjIdx] < UpperBound[AdjIdx];
234  Index[AdjIdx] += Stride[AdjIdx]) {
235 
236  f(Index);
237  }
238  }
239 };
240 
247 template <int NDIMS> struct NDLoop {
251  template <template <int> class LoopBoundTy, typename FuncTy,
252  template <int> class LoopIndexTy = LoopBoundTy>
253  static __SYCL_ALWAYS_INLINE void iterate(const LoopBoundTy<NDIMS> &UpperBound,
254  FuncTy f) {
255  const LoopIndexTy<NDIMS> LowerBound =
257  const LoopBoundTy<NDIMS> Stride =
259  LoopIndexTy<NDIMS> Index =
261 
262  NDLoopIterateImpl<NDIMS, NDIMS - 1, LoopBoundTy, FuncTy, LoopIndexTy>{
263  LowerBound, Stride, UpperBound, f, Index};
264  }
265 
269  template <template <int> class LoopBoundTy, typename FuncTy,
270  template <int> class LoopIndexTy = LoopBoundTy>
271  static __SYCL_ALWAYS_INLINE void iterate(const LoopIndexTy<NDIMS> &LowerBound,
272  const LoopBoundTy<NDIMS> &Stride,
273  const LoopBoundTy<NDIMS> &UpperBound,
274  FuncTy f) {
275  LoopIndexTy<NDIMS> Index =
277  NDLoopIterateImpl<NDIMS, NDIMS - 1, LoopBoundTy, FuncTy, LoopIndexTy>{
278  LowerBound, Stride, UpperBound, f, Index};
279  }
280 };
281 
282 constexpr size_t getNextPowerOfTwoHelper(size_t Var, size_t Offset) {
283  return Offset != 64
284  ? getNextPowerOfTwoHelper(Var | (Var >> Offset), Offset * 2)
285  : Var;
286 }
287 
288 // Returns the smallest power of two not less than Var
289 constexpr size_t getNextPowerOfTwo(size_t Var) {
290  return getNextPowerOfTwoHelper(Var - 1, 1) + 1;
291 }
292 
293 // Returns linear index by given index and range
294 template <int Dims, template <int> class T, template <int> class U>
295 size_t getLinearIndex(const T<Dims> &Index, const U<Dims> &Range) {
296  size_t LinearIndex = 0;
297  for (int I = 0; I < Dims; ++I)
298  LinearIndex = LinearIndex * Range[I] + Index[I];
299  return LinearIndex;
300 }
301 
302 // Kernel set ID, used to group kernels (represented by OSModule & kernel name
303 // pairs) into disjoint sets based on the kernel distribution among device
304 // images.
305 using KernelSetId = size_t;
306 // Kernel set ID for kernels contained within the SPIR-V file specified via
307 // environment.
308 constexpr KernelSetId SpvFileKSId = 0;
310 
311 template <typename T> struct InlineVariableHelper {
312  static constexpr T value{};
313 };
314 
315 template <typename T> constexpr T InlineVariableHelper<T>::value;
316 } // namespace detail
317 } // namespace sycl
318 } // __SYCL_INLINE_NAMESPACE(cl)
cl::sycl::detail::getRawSyclObjImpl
detail::add_pointer_t< typename decltype(T::impl)::element_type > getRawSyclObjImpl(const T &SyclObject)
Definition: common.hpp:172
cl::sycl::detail::getLinearIndex
size_t getLinearIndex(const T< Dims > &Index, const U< Dims > &Range)
Definition: common.hpp:295
cl::sycl::detail::get< 0 >
Definition: tuple.hpp:75
cl::sycl::detail::getNextPowerOfTwoHelper
constexpr size_t getNextPowerOfTwoHelper(size_t Var, size_t Offset)
Definition: common.hpp:282
T
cl::sycl::detail::SpvFileKSId
constexpr KernelSetId SpvFileKSId
Definition: common.hpp:308
defines_elementary.hpp
cl::sycl::detail::code_location::code_location
constexpr code_location(const char *file, const char *func, int line, int col) noexcept
Definition: common.hpp:52
cl::sycl::detail::createSyclObjFromImpl
T createSyclObjFromImpl(decltype(T::impl) ImplObj)
Definition: common.hpp:180
cl::sycl::detail::code_location::fileName
constexpr const char * fileName() const noexcept
Definition: common.hpp:61
cl::sycl::detail::InitializedVal
Definition: common.hpp:186
cl::sycl::detail::LastKSId
constexpr KernelSetId LastKSId
Definition: common.hpp:309
cl::sycl::detail::NDLoopIterateImpl
Helper class for the NDLoop.
Definition: common.hpp:208
cl::sycl::detail::InlineVariableHelper
Definition: common.hpp:311
cl::sycl::detail::KernelSetId
size_t KernelSetId
Definition: common.hpp:305
cl::sycl::detail::code_location::columnNumber
constexpr unsigned long columnNumber() const noexcept
Definition: common.hpp:60
cl::sycl::detail::code_location
Definition: common.hpp:29
cl::sycl::detail::InitializedVal< 1, T >::get
static T< 1 > get()
Definition: common.hpp:192
cl::sycl::detail::get
Definition: tuple.hpp:59
cl::sycl::detail::InitializedVal< 2, T >::get
static T< 2 > get()
Definition: common.hpp:197
stl_type_traits.hpp
cl::sycl::detail::NDLoop
Generates an NDIMS-dimensional perfect loop nest.
Definition: common.hpp:247
export.hpp
__SYCL_ALWAYS_INLINE
#define __SYCL_ALWAYS_INLINE
Definition: defines_elementary.hpp:29
cl.h
defines.hpp
cl
We provide new interfaces for matrix muliply in this patch:
Definition: access.hpp:13
cl::sycl::detail::stringifyErrorCode
const char * stringifyErrorCode(cl_int error)
Definition: common.cpp:16
cl::sycl::detail::NDLoopIterateImpl::NDLoopIterateImpl
NDLoopIterateImpl(const LoopIndexTy< NDIMS > &LowerBound, const LoopBoundTy< NDIMS > &Stride, const LoopBoundTy< NDIMS > &UpperBound, FuncTy f, LoopIndexTy< NDIMS > &Index)
Definition: common.hpp:209
cl::sycl::detail::getNextPowerOfTwo
constexpr size_t getNextPowerOfTwo(size_t Var)
Definition: common.hpp:289
cl::sycl::detail::code_location::current
static constexpr code_location current(const char *fileName=nullptr, const char *funcName=__builtin_FUNCTION(), unsigned long lineNo=__builtin_LINE(), unsigned long columnNo=0) noexcept
Definition: common.hpp:44
std::get
constexpr tuple_element< I, tuple< Types... > >::type & get(cl::sycl::detail::tuple< Types... > &Arg) noexcept
Definition: tuple.hpp:199
cl::sycl::detail::add_pointer_t
typename std::add_pointer< T >::type add_pointer_t
Definition: stl_type_traits.hpp:37
cl::sycl::detail::getSyclObjImpl
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: common.hpp:163
cl::sycl::cl_int
std::int32_t cl_int
Definition: aliases.hpp:85
exception.hpp
cl::sycl::detail::code_location::functionName
constexpr const char * functionName() const noexcept
Definition: common.hpp:62
cl::sycl::detail::NDLoopIterateImpl< NDIMS, 0, LoopBoundTy, FuncTy, LoopIndexTy >::NDLoopIterateImpl
NDLoopIterateImpl(const LoopIndexTy< NDIMS > &LowerBound, const LoopBoundTy< NDIMS > &Stride, const LoopBoundTy< NDIMS > &UpperBound, FuncTy f, LoopIndexTy< NDIMS > &Index)
Definition: common.hpp:227
cl::sycl::detail::codeToString
static std::string codeToString(cl_int code)
Definition: common.hpp:80
cl::sycl::detail::NDLoop::iterate
static __SYCL_ALWAYS_INLINE void iterate(const LoopBoundTy< NDIMS > &UpperBound, FuncTy f)
Generates ND loop nest with {0,..0} .
Definition: common.hpp:253
cl::sycl::detail::InitializedVal< 3, T >::get
static T< 3 > get()
Definition: common.hpp:202
cl::sycl::detail::code_location::lineNumber
constexpr unsigned long lineNumber() const noexcept
Definition: common.hpp:59
cl::sycl::detail::code_location::code_location
constexpr code_location() noexcept
Definition: common.hpp:56
cl::sycl::detail::NDLoop::iterate
static __SYCL_ALWAYS_INLINE void iterate(const LoopIndexTy< NDIMS > &LowerBound, const LoopBoundTy< NDIMS > &Stride, const LoopBoundTy< NDIMS > &UpperBound, FuncTy f)
Generates ND loop nest with LowerBound .
Definition: common.hpp:271
__SYCL_INLINE_NAMESPACE
#define __SYCL_INLINE_NAMESPACE(X)
Definition: defines_elementary.hpp:12