17 #if defined(__SYCL_RT_OS_LINUX)
29 const char LockCacheItem::LockSuffix[] =
".lock";
31 LockCacheItem::LockCacheItem(
const std::string &Path)
32 : FileName(Path + LockSuffix) {
36 if ((fd = open(FileName.c_str(), O_CREAT | O_EXCL, S_IWRITE)) != -1) {
45 if (Owned && std::remove(FileName.c_str()))
62 static auto MaxImgSize = getNumParam<SYCL_CACHE_MAX_DEVICE_IMAGE_SIZE>(
63 DEFAULT_MAX_DEVICE_IMAGE_SIZE);
64 static auto MinImgSize = getNumParam<SYCL_CACHE_MIN_DEVICE_IMAGE_SIZE>(
65 DEFAULT_MIN_DEVICE_IMAGE_SIZE);
69 if ((MaxImgSize && (Img.
getSize() > MaxImgSize)) ||
70 (MinImgSize && (Img.
getSize() < MinImgSize)))
80 const SerializedObj &SpecConsts,
const std::string &BuildOptionsString,
83 if (!isImageCached(Img))
97 FileName = DirName +
"/" + std::to_string(i++);
100 unsigned int DeviceNum = 0;
106 std::vector<size_t> BinarySizes(DeviceNum);
109 sizeof(size_t) * BinarySizes.size(), BinarySizes.data(),
nullptr);
111 std::vector<std::vector<char>> Result;
112 std::vector<char *> Pointers;
113 for (
size_t I = 0; I < BinarySizes.size(); ++I) {
114 Result.emplace_back(BinarySizes[I]);
115 Pointers.push_back(Result[I].data());
119 sizeof(
char *) * Pointers.size(),
120 Pointers.data(),
nullptr);
125 if (Lock.isOwned()) {
126 std::string FullFileName = FileName +
".bin";
127 writeBinaryDataToFile(FullFileName, Result);
128 trace(
"device binary has been cached: " + FullFileName);
129 writeSourceItem(FileName +
".src", Device, Img, SpecConsts,
143 const SerializedObj &SpecConsts,
const std::string &BuildOptionsString) {
145 if (!isImageCached(Img))
156 std::string FileName{Path +
"/" + std::to_string(i)};
161 isCacheItemSrcEqual(FileName +
".src", Device, Img, SpecConsts,
162 BuildOptionsString)) {
164 std::string FullFileName = FileName +
".bin";
165 std::vector<std::vector<char>> res =
166 readBinaryDataFromFile(FullFileName);
167 trace(
"using cached device binary: " + FullFileName);
173 FileName = Path +
"/" + std::to_string(++i);
180 std::string PersistentDeviceCodeCache::getDeviceIDString(
const device &Device) {
191 void PersistentDeviceCodeCache::writeBinaryDataToFile(
192 const std::string &FileName,
const std::vector<std::vector<char>> &Data) {
193 std::ofstream FileStream{FileName, std::ios::binary};
195 size_t Size = Data.size();
196 FileStream.write((
char *)&Size,
sizeof(Size));
198 for (
size_t i = 0; i < Data.size(); ++i) {
199 Size = Data[i].size();
200 FileStream.write((
char *)&Size,
sizeof(Size));
201 FileStream.write(Data[i].data(), Size);
204 if (FileStream.fail())
205 trace(
"Failed to write binary file " + FileName);
211 std::vector<std::vector<char>>
212 PersistentDeviceCodeCache::readBinaryDataFromFile(
const std::string &FileName) {
213 std::ifstream FileStream{FileName, std::ios::binary};
214 size_t ImgNum = 0, ImgSize = 0;
215 FileStream.read((
char *)&ImgNum,
sizeof(ImgNum));
217 std::vector<std::vector<char>> Res(ImgNum);
218 for (
size_t i = 0; i < ImgNum; ++i) {
219 FileStream.read((
char *)&ImgSize,
sizeof(ImgSize));
221 std::vector<char> ImgData(ImgSize);
222 FileStream.read(ImgData.data(), ImgSize);
224 Res[i] = std::move(ImgData);
228 if (FileStream.fail()) {
229 trace(
"Failed to read binary file from " + FileName);
240 void PersistentDeviceCodeCache::writeSourceItem(
241 const std::string &FileName,
const device &Device,
242 const RTDeviceBinaryImage &Img,
const SerializedObj &SpecConsts,
243 const std::string &BuildOptionsString) {
244 std::ofstream FileStream{FileName, std::ios::binary};
246 std::string DeviceString{getDeviceIDString(Device)};
247 size_t Size = DeviceString.size();
248 FileStream.write((
char *)&Size,
sizeof(Size));
249 FileStream.write(DeviceString.data(), Size);
251 Size = BuildOptionsString.size();
252 FileStream.write((
char *)&Size,
sizeof(Size));
253 FileStream.write(BuildOptionsString.data(), Size);
255 Size = SpecConsts.size();
256 FileStream.write((
char *)&Size,
sizeof(Size));
257 FileStream.write((
const char *)SpecConsts.data(), Size);
259 Size = Img.getSize();
260 FileStream.write((
char *)&Size,
sizeof(Size));
261 FileStream.write((
const char *)Img.getRawData().BinaryStart, Size);
264 if (FileStream.fail()) {
265 trace(
"Failed to write source file to " + FileName);
272 bool PersistentDeviceCodeCache::isCacheItemSrcEqual(
273 const std::string &FileName,
const device &Device,
274 const RTDeviceBinaryImage &Img,
const SerializedObj &SpecConsts,
275 const std::string &BuildOptionsString) {
276 std::ifstream FileStream{FileName, std::ios::binary};
278 std::string ImgString{(
const char *)Img.getRawData().BinaryStart,
280 std::string SpecConstsString{(
const char *)SpecConsts.data(),
284 FileStream.read((
char *)&Size,
sizeof(Size));
285 std::string res(Size,
'\0');
286 FileStream.read(&res[0], Size);
287 if (getDeviceIDString(Device).compare(res))
290 FileStream.read((
char *)&Size,
sizeof(Size));
292 FileStream.read(&res[0], Size);
293 if (BuildOptionsString.compare(res))
296 FileStream.read((
char *)&Size,
sizeof(Size));
298 FileStream.read(&res[0], Size);
299 if (SpecConstsString.compare(res))
302 FileStream.read((
char *)&Size,
sizeof(Size));
304 FileStream.read(&res[0], Size);
305 if (ImgString.compare(res))
310 if (FileStream.fail()) {
311 trace(
"Failed to read source file from " + FileName);
322 const SerializedObj &SpecConsts,
const std::string &BuildOptionsString) {
323 static std::string cache_root{getRootDir()};
324 if (cache_root.empty()) {
325 trace(
"Disable persistent cache due to unconfigured cache root.");
331 std::string DeviceString{getDeviceIDString(Device)};
332 std::string SpecConstsString{(
const char *)SpecConsts.data(),
334 std::hash<std::string> StringHasher{};
336 return cache_root +
"/" + std::to_string(StringHasher(DeviceString)) +
"/" +
337 std::to_string(StringHasher(ImgString)) +
"/" +
338 std::to_string(StringHasher(SpecConstsString)) +
"/" +
339 std::to_string(StringHasher(BuildOptionsString));
352 constexpr
bool Default =
false;
358 <<
" environment variable is deprecated "
359 <<
"and has no effect. By default, persistent device code caching is "
360 << (Default ?
"enabled." :
"disabled.") <<
" Use "
362 <<
"=1/0 to enable/disable.\n";
368 if (!std::strcmp(RawVal,
"0")) {
370 }
else if (!std::strcmp(RawVal,
"1")) {
374 std::string{
"Invalid value for bool configuration variable "} +
402 bool PersistentDeviceCodeCache::isEnabled() {
412 std::string PersistentDeviceCodeCache::getRootDir() {
417 constexpr
char DeviceCodeCacheDir[] =
"/libsycl_cache";
420 #if defined(__SYCL_RT_OS_LINUX)
421 static const char *CacheDir = std::getenv(
"XDG_CACHE_HOME");
422 static const char *HomeDir = std::getenv(
"HOME");
423 if (!CacheDir && !HomeDir)
425 static std::string Res{
426 std::string(CacheDir ? CacheDir : (std::string(HomeDir) +
"/.cache")) +
429 static const char *AppDataDir = std::getenv(
"AppData");
432 static std::string Res{std::string(AppDataDir) + DeviceCodeCacheDir};