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(urProgramGetInfo, NativePrg, UR_PROGRAM_INFO_NUM_DEVICES,
135 sizeof(DeviceNum), &DeviceNum,
nullptr);
137 std::vector<size_t> BinarySizes(DeviceNum);
138 Plugin->call(urProgramGetInfo, NativePrg, UR_PROGRAM_INFO_BINARY_SIZES,
139 sizeof(
size_t) * BinarySizes.size(), BinarySizes.data(),
142 std::vector<std::vector<char>> Result;
143 std::vector<char *> Pointers;
144 for (
size_t I = 0; I < BinarySizes.size(); ++I) {
145 Result.emplace_back(BinarySizes[I]);
146 Pointers.push_back(Result[I].data());
149 Plugin->call(urProgramGetInfo, NativePrg, UR_PROGRAM_INFO_BINARIES,
150 sizeof(
char *) * Pointers.size(), Pointers.data(),
nullptr);
152 std::string FileName;
154 FileName = DirName +
"/" + std::to_string(i++);
161 if (Lock.isOwned()) {
162 std::string FullFileName = FileName +
".bin";
163 writeBinaryDataToFile(FullFileName, Result);
164 trace(
"device binary has been cached: " + FullFileName);
165 writeSourceItem(FileName +
".src", Device, SortedImgs, SpecConsts,
170 }
catch (std::exception &e) {
172 std::string(
"exception encountered making persistent cache: ") +
176 std::string(
"error outputting persistent cache: ") +
177 std::strerror(errno));
186 const device &Device,
const std::vector<const RTDeviceBinaryImage *> &Imgs,
187 const SerializedObj &SpecConsts,
const std::string &BuildOptionsString) {
189 if (!areImagesCacheable(Imgs))
192 std::vector<const RTDeviceBinaryImage *> SortedImgs =
getSortedImages(Imgs);
201 std::string FileName{Path +
"/" + std::to_string(i)};
206 isCacheItemSrcEqual(FileName +
".src", Device, SortedImgs, SpecConsts,
207 BuildOptionsString)) {
209 std::string FullFileName = FileName +
".bin";
210 std::vector<std::vector<char>> res =
211 readBinaryDataFromFile(FullFileName);
212 trace(
"using cached device binary: " + FullFileName);
218 FileName = Path +
"/" + std::to_string(++i);
225 std::string PersistentDeviceCodeCache::getDeviceIDString(
const device &Device) {
226 return Device.
get_platform().get_info<sycl::info::platform::name>() +
"/" +
227 Device.
get_info<sycl::info::device::name>() +
"/" +
228 Device.
get_info<sycl::info::device::version>() +
"/" +
229 Device.
get_info<sycl::info::device::driver_version>();
236 void PersistentDeviceCodeCache::writeBinaryDataToFile(
237 const std::string &FileName,
const std::vector<std::vector<char>> &Data) {
238 std::ofstream FileStream{FileName, std::ios::binary};
240 size_t Size = Data.size();
241 FileStream.write((
char *)&Size,
sizeof(Size));
243 for (
size_t i = 0; i < Data.size(); ++i) {
244 Size = Data[i].size();
245 FileStream.write((
char *)&Size,
sizeof(Size));
246 FileStream.write(Data[i].data(), Size);
249 if (FileStream.fail())
250 trace(
"Failed to write binary file " + FileName);
256 std::vector<std::vector<char>>
257 PersistentDeviceCodeCache::readBinaryDataFromFile(
const std::string &FileName) {
258 std::ifstream FileStream{FileName, std::ios::binary};
259 size_t ImgNum = 0, ImgSize = 0;
260 FileStream.read((
char *)&ImgNum,
sizeof(ImgNum));
262 std::vector<std::vector<char>> Res(ImgNum);
263 for (
size_t i = 0; i < ImgNum; ++i) {
264 FileStream.read((
char *)&ImgSize,
sizeof(ImgSize));
266 std::vector<char> ImgData(ImgSize);
267 FileStream.read(ImgData.data(), ImgSize);
269 Res[i] = std::move(ImgData);
273 if (FileStream.fail()) {
274 trace(
"Failed to read binary file from " + FileName);
285 void PersistentDeviceCodeCache::writeSourceItem(
286 const std::string &FileName,
const device &Device,
287 const std::vector<const RTDeviceBinaryImage *> &SortedImgs,
288 const SerializedObj &SpecConsts,
const std::string &BuildOptionsString) {
289 std::ofstream FileStream{FileName, std::ios::binary};
291 std::string DeviceString{getDeviceIDString(Device)};
292 size_t Size = DeviceString.size();
293 FileStream.write((
char *)&Size,
sizeof(Size));
294 FileStream.write(DeviceString.data(), Size);
296 Size = BuildOptionsString.size();
297 FileStream.write((
char *)&Size,
sizeof(Size));
298 FileStream.write(BuildOptionsString.data(), Size);
300 Size = SpecConsts.size();
301 FileStream.write((
char *)&Size,
sizeof(Size));
302 FileStream.write((
const char *)SpecConsts.data(), Size);
305 for (
const RTDeviceBinaryImage *Img : SortedImgs)
306 Size += Img->getSize();
307 FileStream.write((
char *)&Size,
sizeof(Size));
308 for (
const RTDeviceBinaryImage *Img : SortedImgs)
309 FileStream.write((
const char *)Img->getRawData().BinaryStart,
313 if (FileStream.fail()) {
314 trace(
"Failed to write source file to " + FileName);
321 bool PersistentDeviceCodeCache::isCacheItemSrcEqual(
322 const std::string &FileName,
const device &Device,
323 const std::vector<const RTDeviceBinaryImage *> &SortedImgs,
324 const SerializedObj &SpecConsts,
const std::string &BuildOptionsString) {
325 std::ifstream FileStream{FileName, std::ios::binary};
327 std::string ImgsString;
328 for (
const RTDeviceBinaryImage *Img : SortedImgs)
329 ImgsString.append((
const char *)Img->getRawData().BinaryStart,
331 std::string SpecConstsString{(
const char *)SpecConsts.data(),
335 FileStream.read((
char *)&Size,
sizeof(Size));
336 std::string res(Size,
'\0');
337 FileStream.read(&res[0], Size);
338 if (getDeviceIDString(Device).
compare(res))
341 FileStream.read((
char *)&Size,
sizeof(Size));
343 FileStream.read(&res[0], Size);
344 if (BuildOptionsString.compare(res))
347 FileStream.read((
char *)&Size,
sizeof(Size));
349 FileStream.read(&res[0], Size);
350 if (SpecConstsString.compare(res))
353 FileStream.read((
char *)&Size,
sizeof(Size));
355 FileStream.read(&res[0], Size);
356 if (ImgsString.compare(res))
361 if (FileStream.fail()) {
362 trace(
"Failed to read source file from " + FileName);
372 const device &Device,
const std::vector<const RTDeviceBinaryImage *> &Imgs,
373 const SerializedObj &SpecConsts,
const std::string &BuildOptionsString) {
374 std::string cache_root{getRootDir()};
375 if (cache_root.empty()) {
376 trace(
"Disable persistent cache due to unconfigured cache root.");
380 std::string ImgsString;
382 if (Img->getRawData().BinaryStart)
383 ImgsString.append((
const char *)Img->getRawData().BinaryStart,
386 std::string DeviceString{getDeviceIDString(Device)};
387 std::string SpecConstsString{(
const char *)SpecConsts.data(),
389 std::hash<std::string> StringHasher{};
391 return cache_root +
"/" + std::to_string(StringHasher(DeviceString)) +
"/" +
392 std::to_string(StringHasher(ImgsString)) +
"/" +
393 std::to_string(StringHasher(SpecConstsString)) +
"/" +
394 std::to_string(StringHasher(BuildOptionsString));
399 bool PersistentDeviceCodeCache::isEnabled() {
401 static bool FirstCheck =
true;
406 return CacheIsEnabled;
411 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