DPC++ Runtime
Runtime libraries for oneAPI DPC++
persistent_device_code_cache.hpp
Go to the documentation of this file.
1 //==---------- persistent_device_code_cache.hpp -----------------*- C++-*---==//
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 <detail/config.hpp>
13 #include <fcntl.h>
14 #include <string>
15 #include <sycl/detail/os_util.hpp>
16 #include <sycl/detail/pi.hpp>
17 #include <sycl/detail/util.hpp>
18 #include <sycl/device.hpp>
19 #include <sys/stat.h>
20 #include <thread>
21 #include <vector>
22 
23 namespace sycl {
25 namespace detail {
26 
27 /* This is temporary solution until std::filesystem is available when SYCL RT
28  * is moved to c++17 standard*/
29 std::string getDirName(const char *Path);
30 
31 /* The class manages inter-process synchronization:
32  * - Path passed to the constructor is appended with .lock and used as lock
33  * file.
34  * - All operations are not blocking and failure ignoring (diagnostic may be
35  * sent to std::cerr when SYCL_CACHE_TRACE environment variable is set).
36  * - There are two modes of accessing shared resource:
37  * - write access assumes that lock is acquired (object is created and
38  * isOwned() method confirms that current executor owns the lock);
39  * - read access checks that the lock is not acquired for write by others
40  * with the help of isLocked() method.
41  */
43 private:
44  const std::string FileName;
45  bool Owned = false;
46  static const char LockSuffix[];
47 
48 public:
49  LockCacheItem(const std::string &Path);
50 
51  bool isOwned() { return Owned; }
52  static bool isLocked(const std::string &Path) {
53  return OSUtil::isPathPresent(Path + LockSuffix);
54  }
55  ~LockCacheItem();
56 };
57 /* End of temporary solution*/
58 
60  /* The device code images are stored on file system using structure below:
61  * <cache_root>/
62  * <device_hash>/
63  * <device_image_hash>/
64  * <spec_constants_values_hash>/
65  * <build_options_hash>/
66  * <n>.src
67  * <n>.bin
68  * .lock
69  * <cache_root> - root directory storing cache files;
70  * <device_hash> - hash out of device information used to
71  * identify target device;
72  * <device_image_hash> - hash made out of device image used as
73  * input for the JIT compilation;
74  * <spec_constants_values_hash> - hash for specialization constants values;
75  * <build_options_hash> - hash for all build options;
76  * <n> - sequential number of hash collisions.
77  * When hashes match for the specific build
78  * but full values don't, new cache item is
79  * added with incremented value(enumeration
80  * started from 0).
81  * Two files per cache item are stored on disk:
82  * <n>.src - contains full values for build parameters (device information,
83  * specialization constant values, build options, device image)
84  * which is used to resolve hash collisions and analysis of
85  * cached items.
86  * <n>.bin - contains built device code.
87  * <n>.lock - cache item lock file. It is created when data is saved to
88  * filesystem. On read operation the absence of file is checked
89  * but it is not created to avoid lock.
90  * All filesystem operation failures are not treated as SYCL errors and
91  * ignored. If such errors happen warning messages are written to std::cerr
92  * and:
93  * - on cache write operation cache item is not created;
94  * - on cache read operation it is treated as cache miss.
95  */
96 private:
97  /* Write built binary to persistent cache
98  * Format: numImages, 1stImageSize, Image[, NthImageSize, NthImage...]
99  */
100  static void writeBinaryDataToFile(const std::string &FileName,
101  const std::vector<std::vector<char>> &Data);
102 
103  /* Read built binary to persistent cache
104  * Format: numImages, 1stImageSize, Image[, NthImageSize, NthImage...]
105  */
106  static std::vector<std::vector<char>>
107  readBinaryDataFromFile(const std::string &FileName);
108 
109  /* Writing cache item key sources to be used for reliable identification
110  * Format: Four pairs of [size, value] for device, build options,
111  * specialization constant values, device code SPIR-V image.
112  */
113  static void writeSourceItem(const std::string &FileName, const device &Device,
114  const RTDeviceBinaryImage &Img,
115  const SerializedObj &SpecConsts,
116  const std::string &BuildOptionsString);
117 
118  /* Check that cache item key sources are equal to the current program
119  */
120  static bool isCacheItemSrcEqual(const std::string &FileName,
121  const device &Device,
122  const RTDeviceBinaryImage &Img,
123  const SerializedObj &SpecConsts,
124  const std::string &BuildOptionsString);
125 
126  /* Check if on-disk cache enabled.
127  */
128  static bool isEnabled();
129 
130  /* Returns the path to directory storing persistent device code cache.*/
131  static std::string getRootDir();
132 
133  /* Form string representing device version */
134  static std::string getDeviceIDString(const device &Device);
135 
136  /* Returns true if specified image should be cached on disk. It checks if
137  * cache is enabled, image has SPIRV type and matches thresholds. */
138  static bool isImageCached(const RTDeviceBinaryImage &Img);
139 
140  /* Returns value of specified parameter. Default value is used if failure
141  * happens during obtaining value. */
142  template <ConfigID Config>
143  static unsigned long getNumParam(unsigned long Default) {
144  auto Value = SYCLConfig<Config>::get();
145  try {
146  if (Value)
147  return std::stol(Value);
148  } catch (std::exception const &) {
149  PersistentDeviceCodeCache::trace("Invalid value provided, use default " +
150  std::to_string(Default));
151  }
152  return Default;
153  }
154 
155  /* Default value for minimum device code size to be cached on disk in bytes */
156  static constexpr unsigned long DEFAULT_MIN_DEVICE_IMAGE_SIZE = 0;
157 
158  /* Default value for maximum device code size to be cached on disk in bytes */
159  static constexpr unsigned long DEFAULT_MAX_DEVICE_IMAGE_SIZE =
160  1024 * 1024 * 1024;
161 
162 public:
163  /* Get directory name for storing current cache item
164  */
165  static std::string getCacheItemPath(const device &Device,
166  const RTDeviceBinaryImage &Img,
167  const SerializedObj &SpecConsts,
168  const std::string &BuildOptionsString);
169 
170  /* Program binaries built for one or more devices are read from persistent
171  * cache and returned in form of vector of programs. Each binary program is
172  * stored in vector of chars.
173  */
174  static std::vector<std::vector<char>>
175  getItemFromDisc(const device &Device, const RTDeviceBinaryImage &Img,
176  const SerializedObj &SpecConsts,
177  const std::string &BuildOptionsString);
178 
179  /* Stores build program in persisten cache
180  */
181  static void putItemToDisc(const device &Device,
182  const RTDeviceBinaryImage &Img,
183  const SerializedObj &SpecConsts,
184  const std::string &BuildOptionsString,
185  const RT::PiProgram &NativePrg);
186 
187  /* Sends message to std:cerr stream when SYCL_CACHE_TRACE environemnt is set*/
188  static void trace(const std::string &msg) {
189  static const char *TraceEnabled = SYCLConfig<SYCL_CACHE_TRACE>::get();
190  if (TraceEnabled)
191  std::cerr << "*** Code caching: " << msg << std::endl;
192  }
193 };
194 } // namespace detail
195 } // __SYCL_INLINE_VER_NAMESPACE(_V1)
196 } // namespace sycl
static bool isLocked(const std::string &Path)
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:49
#define __SYCL_INLINE_VER_NAMESPACE(X)
constexpr tuple_element< I, tuple< Types... > >::type & get(sycl::detail::tuple< Types... > &Arg) noexcept
Definition: tuple.hpp:199
__SYCL_EXTERN_STREAM_ATTRS ostream cerr
Linked to standard error (unbuffered)
bool trace(TraceLevel level)
Definition: pi.cpp:394
::pi_program PiProgram
Definition: pi.hpp:115
std::string getDirName(const char *Path)
std::vector< unsigned char > SerializedObj
Definition: util.hpp:68
---— Error handling, matching OpenCL plugin semantics.
Definition: access.hpp:14
C++ wrapper of extern "C" PI interfaces.
@ Device