Skip to content

Commit ec97165

Browse files
authored
[SYCL] Persistent program cache (#3391)
First part of implementation for persistent cache of device programs following sycl/doc/KernelProgramCache.md: Programs built for target device are stored in on-disk cache and used next time when the same application is executed. What is done: - storing and loading files when built program is not found in in-memory cache; - file system concurrent access management (lock file is created per cache item while data is being written, read operation does not lock the cache item); - thread safety for persistent device code cache is not needed as soon as build/in-memory cache part is managed by program_manager and persisten_device_code_cache does not store data shared between threads. - Implement support for environment variables affecting cache: SYCL_CACHE_DIR SYCL_CACHE_TRACE SYCL_CACHE_DISABLE_PERSISTENT SYCL_CACHE_MIN_DEVICE_IMAGE_SIZE SYCL_CACHE_MAX_DEVICE_IMAGE_SIZE SYCL_CACHE_MIN_DEVICE_IMAGE_SIZE - Errors happening during filesystem operation cause corresponding cache operation silently ends: - for read operation, cache miss happens (without SYCL error), message is sent to std::cerr if SYCL_CACHE_TRACE is set; - for write operation, no cache item stored (without SYCL error), message is sent to std::cerr if SYCL_CACHE_TRACE is set; - Add tests: - on-device tests for basic cache functionality and environment variables processing; - unit tests for concurrent access to filesystem and error management. To be done in next patches: - implement rest of environment variables and extend them to both in-memory and persistent cache; - implement kernel eviction mechanism for on-device and in-memory caches.
1 parent f27bb01 commit ec97165

19 files changed

+1456
-19
lines changed

sycl/doc/EnvironmentVariables.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ subject to change. Do not rely on these variables in production code.
3535
| SYCL_DISABLE_PARALLEL_FOR_RANGE_ROUNDING | Any(\*) | Disables automatic rounding-up of parallel_for invocation ranges. |
3636
| SYCL_ENABLE_PCI | Integer | When set to 1, enables obtaining the GPU PCI address when using the Level Zero backend. The default is 0. |
3737
| SYCL_HOST_UNIFIED_MEMORY | Integer | Enforce host unified memory support or lack of it for the execution graph builder. If set to 0, it is enforced as not supported by all devices. If set to 1, it is enforced as supported by all devices. |
38+
| SYCL_CACHE_DIR | Path | Path to persistent cache root directory. Default values are `%AppData%\libsycl_cache` for Windows and `$XDG_CACHE_HOME/libsycl_cache` on Linux, if XDG_CACHE_HOME is not set then `$HOME/.cache/libsycl_cache`. |
39+
| SYCL_CACHE_TRACE | Any(\*) | Enables printing messages to std::cerr when non-blocking failures happen (e.g. unable to access cache item file). Default values if off. |
40+
| SYCL_CACHE_DISABLE_PERSISTENT | Any(\*) | Switches persistent cache switch off. Default value is ON. |
41+
| SYCL_CACHE_EVICTION_DISABLE | Any(\*) | Switches cache eviction off. Default value is ON. |
42+
| SYCL_CACHE_MAX_SIZE | Positive integer | Cache eviction is triggered once total size of cached images exceeds the value in megabytes (default - 8 192 for 8 GB). Set to 0 to disable size-based cache eviction. |
43+
| SYCL_CACHE_THRESHOLD | Positive integer | Cache eviction threshold in days (default value is 7 for 1 week). Set to 0 for disabling time-based cache eviction. |
44+
| SYCL_CACHE_MIN_DEVICE_IMAGE_SIZE | Positive integer | Minimum size of device code image in bytes which is reasonable to cache on disk because disk access operation may take more time than do JIT compilation for it. Default value is 0 to cache all images. |
45+
| SYCL_CACHE_MAX_DEVICE_IMAGE_SIZE | Positive integer | Maximum size of device image in bytes which is cached. Too big kernels may overload disk too fast. Default value is 1 GB. |
3846

3947
`(*) Note: Any means this environment variable is effective when set to any non-null value.`
4048

sycl/doc/KernelProgramCache.md

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,8 @@ three sources of build options:
172172

173173
## Cache configuration
174174

175-
There is set of configuration parameters which can be set as environment variables or parameters in `sycl.conf` and affect cache behavior:
176-
| Environment variable | Values | Description |
177-
| -------------------- | ------ | ----------- |
178-
| `SYCL_CACHE_DIR`| Path | Path to persistent cache root directory. Default values are `%AppData%\Intel\sycl_program_cache` for Windows and `$HOME/intel/sycl_program_cache` on Linux. |
179-
| `SYCL_CACHE_ENABLED` | ON, OFF | Switches persistent cache switch on or off. Default value is ON. |
180-
| `SYCL_CACHE_MAX_SIZE` | Positive integer | Cache eviction is triggered once total size of cached images exceeds the value in megabytes (default - 8 192 for 8 GB). Set to 0 to disable size-based cache eviction. |
181-
| `SYCL_CACHE_THRESHOLD` | Positive integer | Cache eviction threshold in days (default value is 7 for 1 week). Set to 0 for disabling time-based cache eviction. |
182-
| `SYCL_CACHE_MIN_DEVICE_IMAGE_SIZE` | Positive integer | Minimum size of device code image in kilobytes which is reasonable to cache on disk because disk access operation may take more time than do JIT compilation for it. Default value is 0 to cache all images. |
183-
| `SYCL_CACHE_MAX_DEVICE_IMAGE_SIZE` | Positive integer | Maximum size of device image in megabytes which is cached. Too big kernels may overload disk too fast. Default value is 0 to cache all images. |
175+
The environment variables which affect cache behavior are described in
176+
[EnvironmentVariables.md](https://github.com/intel/llvm/blob/sycl/sycl/doc/EnvironmentVariables.md).
184177

185178
## Implementation details
186179

sycl/include/CL/sycl/detail/os_util.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include <cstdint>
1717
#include <cstdlib>
1818
#include <string>
19+
#include <sys/stat.h>
20+
#include <sys/types.h>
1921

2022
#ifdef _WIN32
2123
#define __SYCL_RT_OS_WINDOWS
@@ -80,6 +82,20 @@ class __SYCL_EXPORT OSUtil {
8082

8183
/// Deallocates the memory referenced by \p Ptr.
8284
static void alignedFree(void *Ptr);
85+
86+
/// Make directory recursively and returns zero code on success
87+
static int makeDir(const char *Dir);
88+
89+
/// Checks if specified path is present
90+
static inline bool isPathPresent(const std::string &Path) {
91+
#ifdef __SYCL_RT_OS_WINDOWS
92+
struct _stat Stat;
93+
return !_stat(Path.c_str(), &Stat);
94+
#else
95+
struct stat Stat;
96+
return !stat(Path.c_str(), &Stat);
97+
#endif
98+
}
8399
};
84100

85101
} // namespace detail

sycl/source/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ set(SYCL_SOURCES
137137
"detail/queue_impl.cpp"
138138
"detail/online_compiler/online_compiler.cpp"
139139
"detail/os_util.cpp"
140+
"detail/persistent_device_code_cache.cpp"
140141
"detail/platform_util.cpp"
141142
"detail/reduction.cpp"
142143
"detail/sampler_impl.cpp"

sycl/source/detail/config.def

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,12 @@ CONFIG(SYCL_DEVICE_FILTER, 1024, __SYCL_DEVICE_FILTER)
2020
CONFIG(SYCL_PROGRAM_LINK_OPTIONS, 64, __SYCL_PROGRAM_LINK_OPTIONS)
2121
CONFIG(SYCL_PROGRAM_COMPILE_OPTIONS, 64, __SYCL_PROGRAM_COMPILE_OPTIONS)
2222
CONFIG(SYCL_HOST_UNIFIED_MEMORY, 1, __SYCL_HOST_UNIFIED_MEMORY)
23+
// 260 (Windows limit) - 12 (filename) - 84 (cache directory structure)
24+
CONFIG(SYCL_CACHE_DIR, 164, __SYCL_CACHE_DIR)
25+
CONFIG(SYCL_CACHE_TRACE, 1, __SYCL_CACHE_TRACE)
26+
CONFIG(SYCL_CACHE_DISABLE_PERSISTENT, 1, __SYCL_CACHE_DISABLE_PERSISTENT)
27+
CONFIG(SYCL_CACHE_EVICTION_DISABLE, 1, __SYCL_CACHE_EVICTION_DISABLE)
28+
CONFIG(SYCL_CACHE_MAX_SIZE, 16, __SYCL_CACHE_MAX_SIZE)
29+
CONFIG(SYCL_CACHE_THRESHOLD, 16, __SYCL_CACHE_THRESHOLD)
30+
CONFIG(SYCL_CACHE_MIN_DEVICE_IMAGE_SIZE, 16, __SYCL_CACHE_MIN_DEVICE_IMAGE_SIZE)
31+
CONFIG(SYCL_CACHE_MAX_DEVICE_IMAGE_SIZE, 16, __SYCL_CACHE_MAX_DEVICE_IMAGE_SIZE)

sycl/source/detail/os_util.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@
2424
#include <libgen.h> // for dirname
2525
#include <link.h>
2626
#include <linux/limits.h> // for PATH_MAX
27+
#include <sys/stat.h>
2728
#include <sys/sysinfo.h>
2829

2930
#elif defined(__SYCL_RT_OS_WINDOWS)
3031

3132
#include <Windows.h>
33+
#include <direct.h>
3234
#include <malloc.h>
3335
#include <shlwapi.h>
3436

@@ -211,6 +213,19 @@ std::string OSUtil::getCurrentDSODir() {
211213
return Path;
212214
}
213215

216+
std::string OSUtil::getDirName(const char *Path) {
217+
std::string Tmp(Path);
218+
// Remove trailing directory separators
219+
Tmp.erase(Tmp.find_last_not_of("/\\") + 1, std::string::npos);
220+
221+
int pos = Tmp.find_last_of("/\\");
222+
if (pos != std::string::npos)
223+
return Tmp.substr(0, pos);
224+
225+
// If no directory separator is present return initial path like dirname does
226+
return Tmp;
227+
}
228+
214229
#elif defined(__SYCL_RT_OS_DARWIN)
215230
OSModuleHandle OSUtil::getOSModuleHandle(const void *VirtAddr) {
216231
Dl_info Res;
@@ -258,6 +273,32 @@ void OSUtil::alignedFree(void *Ptr) {
258273
#endif
259274
}
260275

276+
/* This is temporary solution until std::filesystem is available when SYCL RT
277+
* is moved to c++17 standard*/
278+
279+
/* Create directory recursively and return non zero code on success*/
280+
int OSUtil::makeDir(const char *Dir) {
281+
assert((Dir != nullptr) && "Passed null-pointer as directory name.");
282+
if (isPathPresent(Dir))
283+
return 0;
284+
285+
std::string Path{Dir}, CurPath;
286+
size_t pos = 0;
287+
288+
do {
289+
pos = Path.find_first_of("/\\", ++pos);
290+
CurPath = Path.substr(0, pos);
291+
#if defined(__SYCL_RT_OS_LINUX)
292+
auto Res = mkdir(CurPath.c_str(), 0777);
293+
#else
294+
auto Res = _mkdir(CurPath.c_str());
295+
#endif
296+
if (Res && errno != EEXIST)
297+
return Res;
298+
} while (pos != std::string::npos);
299+
return 0;
300+
}
301+
261302
} // namespace detail
262303
} // namespace sycl
263304
} // __SYCL_INLINE_NAMESPACE(cl)

0 commit comments

Comments
 (0)