19 #if defined(__SYCL_RT_OS_POSIX_SUPPORT)
27 inline namespace _V1 {
31 const char LockCacheItem::LockSuffix[] =
".lock";
34 : FileName(Path + LockSuffix) {
38 if ((fd = open(FileName.c_str(), O_CREAT | O_EXCL, S_IWRITE)) != -1) {
43 FileName +
" " + std::strerror(errno));
45 FileName +
" " + std::strerror(errno));
50 if (Owned && std::remove(FileName.c_str()))
64 bool PersistentDeviceCodeCache::areImagesCacheable(
65 const std::vector<const RTDeviceBinaryImage *> &Imgs) {
66 assert(!Imgs.empty());
67 auto Format = Imgs[0]->getFormat();
69 [&Format](
const RTDeviceBinaryImage *Img) {
70 return Img->getFormat() == Format;
72 "All images are expected to have the same format");
83 static auto MaxImgSize = getNumParam<SYCL_CACHE_MAX_DEVICE_IMAGE_SIZE>(
84 DEFAULT_MAX_DEVICE_IMAGE_SIZE);
85 static auto MinImgSize = getNumParam<SYCL_CACHE_MIN_DEVICE_IMAGE_SIZE>(
86 DEFAULT_MIN_DEVICE_IMAGE_SIZE);
91 for (
const RTDeviceBinaryImage *Img : Imgs)
92 TotalSize += Img->getSize();
93 if ((MaxImgSize && (TotalSize > MaxImgSize)) ||
94 (MinImgSize && (TotalSize < MinImgSize)))
100 static std::vector<const RTDeviceBinaryImage *>
102 std::vector<const RTDeviceBinaryImage *> SortedImgs = Imgs;
103 std::sort(SortedImgs.begin(), SortedImgs.end(),
107 return std::strcmp(A->getRawData().EntriesBegin->name,
108 B->getRawData().EntriesBegin->name) < 0;
116 const device &Device,
const std::vector<const RTDeviceBinaryImage *> &Imgs,
117 const SerializedObj &SpecConsts,
const std::string &BuildOptionsString,
118 const ur_program_handle_t &NativePrg) {
120 if (!areImagesCacheable(Imgs))
123 std::vector<const RTDeviceBinaryImage *> SortedImgs =
getSortedImages(Imgs);
124 std::string DirName =
132 unsigned int DeviceNum = 0;
134 Plugin->call<UrApiKind::urProgramGetInfo>(
135 NativePrg, UR_PROGRAM_INFO_NUM_DEVICES,
sizeof(DeviceNum), &DeviceNum,
138 std::vector<size_t> BinarySizes(DeviceNum);
139 Plugin->call<UrApiKind::urProgramGetInfo>(
140 NativePrg, UR_PROGRAM_INFO_BINARY_SIZES,
141 sizeof(size_t) * BinarySizes.size(), BinarySizes.data(),
nullptr);
143 std::vector<std::vector<char>> Result;
144 std::vector<char *> Pointers;
145 for (
size_t I = 0; I < BinarySizes.size(); ++I) {
146 Result.emplace_back(BinarySizes[I]);
147 Pointers.push_back(Result[I].data());
150 Plugin->call<UrApiKind::urProgramGetInfo>(NativePrg, UR_PROGRAM_INFO_BINARIES,
151 sizeof(
char *) * Pointers.size(),
152 Pointers.data(),
nullptr);
154 std::string FileName;
156 FileName = DirName +
"/" + std::to_string(i++);
163 if (Lock.isOwned()) {
164 std::string FullFileName = FileName +
".bin";
165 writeBinaryDataToFile(FullFileName, Result);
166 trace(
"device binary has been cached: " + FullFileName);
167 writeSourceItem(FileName +
".src", Device, SortedImgs, SpecConsts,
172 }
catch (std::exception &e) {
174 std::string(
"exception encountered making persistent cache: ") +
178 std::string(
"error outputting persistent cache: ") +
179 std::strerror(errno));
188 const device &Device,
const std::vector<const RTDeviceBinaryImage *> &Imgs,
189 const SerializedObj &SpecConsts,
const std::string &BuildOptionsString) {
191 if (!areImagesCacheable(Imgs))
194 std::vector<const RTDeviceBinaryImage *> SortedImgs =
getSortedImages(Imgs);
203 std::string FileName{Path +
"/" + std::to_string(i)};
208 isCacheItemSrcEqual(FileName +
".src", Device, SortedImgs, SpecConsts,
209 BuildOptionsString)) {
211 std::string FullFileName = FileName +
".bin";
212 std::vector<std::vector<char>> res =
213 readBinaryDataFromFile(FullFileName);
214 trace(
"using cached device binary: " + FullFileName);
220 FileName = Path +
"/" + std::to_string(++i);
227 std::string PersistentDeviceCodeCache::getDeviceIDString(
const device &Device) {
228 return Device.
get_platform().get_info<sycl::info::platform::name>() +
"/" +
229 Device.
get_info<sycl::info::device::name>() +
"/" +
230 Device.
get_info<sycl::info::device::version>() +
"/" +
231 Device.
get_info<sycl::info::device::driver_version>();
238 void PersistentDeviceCodeCache::writeBinaryDataToFile(
239 const std::string &FileName,
const std::vector<std::vector<char>> &Data) {
240 std::ofstream FileStream{FileName, std::ios::binary};
242 size_t Size = Data.size();
243 FileStream.write((
char *)&Size,
sizeof(Size));
245 for (
size_t i = 0; i < Data.size(); ++i) {
246 Size = Data[i].size();
247 FileStream.write((
char *)&Size,
sizeof(Size));
248 FileStream.write(Data[i].data(), Size);
251 if (FileStream.fail())
252 trace(
"Failed to write binary file " + FileName);
258 std::vector<std::vector<char>>
259 PersistentDeviceCodeCache::readBinaryDataFromFile(
const std::string &FileName) {
260 std::ifstream FileStream{FileName, std::ios::binary};
261 size_t ImgNum = 0, ImgSize = 0;
262 FileStream.read((
char *)&ImgNum,
sizeof(ImgNum));
264 std::vector<std::vector<char>> Res(ImgNum);
265 for (
size_t i = 0; i < ImgNum; ++i) {
266 FileStream.read((
char *)&ImgSize,
sizeof(ImgSize));
268 std::vector<char> ImgData(ImgSize);
269 FileStream.read(ImgData.data(), ImgSize);
271 Res[i] = std::move(ImgData);
275 if (FileStream.fail()) {
276 trace(
"Failed to read binary file from " + FileName);
287 void PersistentDeviceCodeCache::writeSourceItem(
288 const std::string &FileName,
const device &Device,
289 const std::vector<const RTDeviceBinaryImage *> &SortedImgs,
290 const SerializedObj &SpecConsts,
const std::string &BuildOptionsString) {
291 std::ofstream FileStream{FileName, std::ios::binary};
293 std::string DeviceString{getDeviceIDString(Device)};
294 size_t Size = DeviceString.size();
295 FileStream.write((
char *)&Size,
sizeof(Size));
296 FileStream.write(DeviceString.data(), Size);
298 Size = BuildOptionsString.size();
299 FileStream.write((
char *)&Size,
sizeof(Size));
300 FileStream.write(BuildOptionsString.data(), Size);
302 Size = SpecConsts.size();
303 FileStream.write((
char *)&Size,
sizeof(Size));
304 FileStream.write((
const char *)SpecConsts.data(), Size);
307 for (
const RTDeviceBinaryImage *Img : SortedImgs)
308 Size += Img->getSize();
309 FileStream.write((
char *)&Size,
sizeof(Size));
310 for (
const RTDeviceBinaryImage *Img : SortedImgs)
311 FileStream.write((
const char *)Img->getRawData().BinaryStart,
315 if (FileStream.fail()) {
316 trace(
"Failed to write source file to " + FileName);
323 bool PersistentDeviceCodeCache::isCacheItemSrcEqual(
324 const std::string &FileName,
const device &Device,
325 const std::vector<const RTDeviceBinaryImage *> &SortedImgs,
326 const SerializedObj &SpecConsts,
const std::string &BuildOptionsString) {
327 std::ifstream FileStream{FileName, std::ios::binary};
329 std::string ImgsString;
330 for (
const RTDeviceBinaryImage *Img : SortedImgs)
331 ImgsString.append((
const char *)Img->getRawData().BinaryStart,
333 std::string SpecConstsString{(
const char *)SpecConsts.data(),
337 FileStream.read((
char *)&Size,
sizeof(Size));
338 std::string res(Size,
'\0');
339 FileStream.read(&res[0], Size);
340 if (getDeviceIDString(Device).
compare(res))
343 FileStream.read((
char *)&Size,
sizeof(Size));
345 FileStream.read(&res[0], Size);
346 if (BuildOptionsString.compare(res))
349 FileStream.read((
char *)&Size,
sizeof(Size));
351 FileStream.read(&res[0], Size);
352 if (SpecConstsString.compare(res))
355 FileStream.read((
char *)&Size,
sizeof(Size));
357 FileStream.read(&res[0], Size);
358 if (ImgsString.compare(res))
363 if (FileStream.fail()) {
364 trace(
"Failed to read source file from " + FileName);
374 const device &Device,
const std::vector<const RTDeviceBinaryImage *> &Imgs,
375 const SerializedObj &SpecConsts,
const std::string &BuildOptionsString) {
376 std::string cache_root{getRootDir()};
377 if (cache_root.empty()) {
378 trace(
"Disable persistent cache due to unconfigured cache root.");
382 std::string ImgsString;
384 if (Img->getRawData().BinaryStart)
385 ImgsString.append((
const char *)Img->getRawData().BinaryStart,
388 std::string DeviceString{getDeviceIDString(Device)};
389 std::string SpecConstsString{(
const char *)SpecConsts.data(),
391 std::hash<std::string> StringHasher{};
393 return cache_root +
"/" + std::to_string(StringHasher(DeviceString)) +
"/" +
394 std::to_string(StringHasher(ImgsString)) +
"/" +
395 std::to_string(StringHasher(SpecConstsString)) +
"/" +
396 std::to_string(StringHasher(BuildOptionsString));
401 bool PersistentDeviceCodeCache::isEnabled() {
403 static bool FirstCheck =
true;
408 return CacheIsEnabled;
413 std::string PersistentDeviceCodeCache::getRootDir() {
static bool isLocked(const std::string &Path)
LockCacheItem(const std::string &Path)
static int makeDir(const char *Dir)
Make all directories on the path, throws on error.
static bool isPathPresent(const std::string &Path)
Checks if specified path is present.
static std::string getCacheItemPath(const device &Device, const std::vector< const RTDeviceBinaryImage * > &SortedImgs, const SerializedObj &SpecConsts, const std::string &BuildOptionsString)
static void trace(const std::string &msg)
static std::vector< std::vector< char > > getItemFromDisc(const device &Device, const std::vector< const RTDeviceBinaryImage * > &Imgs, const SerializedObj &SpecConsts, const std::string &BuildOptionsString)
static void putItemToDisc(const device &Device, const std::vector< const RTDeviceBinaryImage * > &Imgs, const SerializedObj &SpecConsts, const std::string &BuildOptionsString, const ur_program_handle_t &NativePrg)
static const char * get()
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
detail::is_device_info_desc< Param >::return_type get_info() const
Queries this SYCL device for information requested by the template parameter param.
platform get_platform() const
Get associated SYCL platform.
sycl_device_binary_type
Types of device binary.
@ SYCL_DEVICE_BINARY_TYPE_SPIRV
@ SYCL_DEVICE_BINARY_TYPE_NATIVE
decltype(Obj::impl) const & getSyclObjImpl(const Obj &SyclObject)
static std::vector< const RTDeviceBinaryImage * > getSortedImages(const std::vector< const RTDeviceBinaryImage * > &Imgs)
static bool IsSupportedImageFormat(ur::DeviceBinaryType Format)
std::vector< unsigned char > SerializedObj
std::enable_if_t< std::is_same_v< std::invoke_result_t< BinaryOperation, ValueT, ValueT >, bool >, bool > compare(const ValueT a, const ValueT b, const BinaryOperation binary_op)
Performs comparison.
bool all_of(const simd_mask< _Tp, _Abi > &) noexcept