Skip to content

Commit 07e6ae4

Browse files
againullKornevNikita
authored andcommitted
[SYCL] Keep the old format of files in persistent cache (#16428)
[PR#16056](#16056) fixed multi-device support for persistent cache but also changed format of the files in persistent cache - we used to write number of binaries before binary size and binary data but stopped doing that because we always have a single binary (for a single device) per file. Because of that new runtime stopped working with persistent cache created by older runtimes. This PR restores the old format of files in persistent cache. For that we need to write number of binaries to the file (before binary size and binary data) though it is always equal to 1 in current implementation. Even in the old implementation we could only put a single binary to the persistent cache in all scenarios, multi-device case wasn't supported, didn't have an API to create a program from multiple binaries. So we can assert that number of binaries is always 1 when reading from the cache.
1 parent 9049280 commit 07e6ae4

File tree

3 files changed

+58
-13
lines changed

3 files changed

+58
-13
lines changed

sycl/source/detail/persistent_device_code_cache.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,11 +367,18 @@ std::string PersistentDeviceCodeCache::getDeviceIDString(const device &Device) {
367367
}
368368

369369
/* Write built binary to persistent cache
370-
* Format: BinarySize, Binary
370+
* Format: NumBinaries(=1), BinarySize, Binary
371371
*/
372372
void PersistentDeviceCodeCache::writeBinaryDataToFile(
373373
const std::string &FileName, const std::vector<char> &Data) {
374374
std::ofstream FileStream{FileName, std::ios::binary};
375+
// The reason why we need to write number of binaries (in current
376+
// implementation always 1) is to keep compatibility with the old format of
377+
// files in persistent cache, so that new runtime can use binaries from
378+
// persistent cache generated by old compiler/runtime.
379+
size_t NumBinaries = 1;
380+
FileStream.write((char *)&NumBinaries, sizeof(NumBinaries));
381+
375382
auto Size = Data.size();
376383
FileStream.write((char *)&Size, sizeof(Size));
377384
FileStream.write(Data.data(), Size);
@@ -380,11 +387,26 @@ void PersistentDeviceCodeCache::writeBinaryDataToFile(
380387
}
381388

382389
/* Read built binary from persistent cache. Each persistent cache file contains
383-
* binary for a single device. Format: BinarySize, Binary
390+
* binary for a single device.
391+
* Format: NumBinaries(=1), BinarySize, Binary
384392
*/
385393
std::vector<char>
386394
PersistentDeviceCodeCache::readBinaryDataFromFile(const std::string &FileName) {
387395
std::ifstream FileStream{FileName, std::ios::binary};
396+
// We ignore this number, we always read single device binary from a file and
397+
// we need this just to keep compatibility with the old format of files in
398+
// persistent cache, so that new runtime can use binaries from persistent
399+
// cache generated by old compiler/runtime.
400+
size_t NumBinaries = 0;
401+
FileStream.read((char *)&NumBinaries, sizeof(NumBinaries));
402+
if (FileStream.fail()) {
403+
trace("Failed to read number of binaries from " + FileName);
404+
return {};
405+
}
406+
// Even in the old implementation we could only put a single binary to the
407+
// persistent cache in all scenarios, multi-device case wasn't supported.
408+
assert(NumBinaries == 1);
409+
388410
size_t BinarySize = 0;
389411
FileStream.read((char *)&BinarySize, sizeof(BinarySize));
390412

sycl/source/detail/persistent_device_code_cache.hpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,19 @@ class PersistentDeviceCodeCache {
9191
*/
9292
private:
9393
/* Write built binary to persistent cache
94-
* Format: BinarySize, Binary
94+
* Format: NumBinaries(=1), BinarySize, Binary
95+
* The reason why we need to write a number of binaries (always 1 in current
96+
* implementation) is to keep compatibility with the old format of files in
97+
* the persistent cache, so that new runtime can use binaries from the
98+
* persistent cache generated by an old compiler/runtime. NumBinaries can be
99+
* removed at next ABI breaking window.
95100
*/
96101
static void writeBinaryDataToFile(const std::string &FileName,
97102
const std::vector<char> &Data);
98103

99-
/* Read built binary to persistent cache
100-
* Format: BinarySize, Binary
104+
/* Read built binary from persistent cache
105+
* Format: NumBinaries(=1), BinarySize, Binary
106+
* See comment above regarding the reason why we need NumBinaries.
101107
*/
102108
static std::vector<char> readBinaryDataFromFile(const std::string &FileName);
103109

sycl/unittests/kernel-and-program/PersistentDeviceCodeCache.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -394,14 +394,14 @@ TEST_P(PersistentDeviceCodeCache, CorruptedCacheFiles) {
394394
// Binary file is corrupted
395395
detail::PersistentDeviceCodeCache::putItemToDisc({Dev}, {&Img}, {},
396396
BuildOptions, NativeProg);
397-
std::ofstream FileStream(ItemDir + "/0.bin",
398-
std::ofstream::out | std::ofstream::trunc);
399-
/* Emulate binary built for 2 devices: first is OK, second is trancated
400-
* from 23 bytes to 4
401-
*/
402-
FileStream << 2 << 12 << "123456789012" << 23 << "1234";
403-
FileStream.close();
404-
EXPECT_FALSE(FileStream.fail()) << "Failed to create trancated binary file";
397+
{
398+
std::ofstream FileStream(ItemDir + "/0.bin",
399+
std::ofstream::out | std::ofstream::trunc);
400+
// Emulate binary which is truncated from 23 bytes to 4.
401+
FileStream << 1 << 23 << "1234";
402+
FileStream.close();
403+
EXPECT_FALSE(FileStream.fail()) << "Failed to create trancated binary file";
404+
}
405405
Res = detail::PersistentDeviceCodeCache::getItemFromDisc({Dev}, {&Img}, {},
406406
BuildOptions);
407407
EXPECT_EQ(Res.size(), static_cast<size_t>(0))
@@ -421,6 +421,23 @@ TEST_P(PersistentDeviceCodeCache, CorruptedCacheFiles) {
421421
EXPECT_EQ(Res.size(), static_cast<size_t>(0))
422422
<< "Item with corrupted binary file was read";
423423
ASSERT_NO_ERROR(llvm::sys::fs::remove_directories(ItemDir));
424+
425+
// Unexpected 2 binaries in a single file.
426+
detail::PersistentDeviceCodeCache::putItemToDisc({Dev}, {&Img}, {},
427+
BuildOptions, NativeProg);
428+
{
429+
std::ofstream FileStream(ItemDir + "/0.bin",
430+
std::ofstream::out | std::ofstream::trunc);
431+
// Emulate binaries for 2 devices in a single file.
432+
FileStream << 2 << 12 << "123456789012" << 4 << "1234";
433+
FileStream.close();
434+
EXPECT_FALSE(FileStream.fail())
435+
<< "Failed to create a file containing 2 binaries";
436+
}
437+
ASSERT_DEATH(detail::PersistentDeviceCodeCache::getItemFromDisc(
438+
{Dev}, {&Img}, {}, BuildOptions),
439+
"NumBinaries == 1");
440+
ASSERT_NO_ERROR(llvm::sys::fs::remove_directories(ItemDir));
424441
}
425442

426443
/* Checks that lock file affects cache operations as expected:

0 commit comments

Comments
 (0)