diff options
author | Michael Jones <michael_jones> | 2022-11-11 21:10:16 +0300 |
---|---|---|
committer | Michael Jones <michael_p_jones@apple.com> | 2022-11-11 21:10:29 +0300 |
commit | 2c596319a4888aa40bfdf41f9ea5d446179141d0 (patch) | |
tree | 747a944a3b3cfe9714d260672ee56a8b7ec07280 | |
parent | 6f6a0185f2be5074bcde4082dd3d1e31843151d9 (diff) |
Cycles: Cache only up to 5 kernels of each type on Metal
This patch adapts D14754 for the Metal backend. Kernels of the same type are already organised into subdirectories which simplifies type matching.
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D16469
-rw-r--r-- | intern/cycles/device/metal/kernel.mm | 7 | ||||
-rw-r--r-- | intern/cycles/util/path.cpp | 56 | ||||
-rw-r--r-- | intern/cycles/util/path.h | 11 |
3 files changed, 62 insertions, 12 deletions
diff --git a/intern/cycles/device/metal/kernel.mm b/intern/cycles/device/metal/kernel.mm index dc8af9a5358..35cf832c537 100644 --- a/intern/cycles/device/metal/kernel.mm +++ b/intern/cycles/device/metal/kernel.mm @@ -618,7 +618,9 @@ void MetalKernelPipeline::compile() metalbin_path = path_cache_get(path_join("kernels", metalbin_name)); path_create_directories(metalbin_path); - if (path_exists(metalbin_path) && use_binary_archive) { + /* Retrieve shader binary from disk, and update the file timestamp for LRU purging to work as + * intended. */ + if (use_binary_archive && path_cache_kernel_exists_and_mark_used(metalbin_path)) { if (@available(macOS 11.0, *)) { MTLBinaryArchiveDescriptor *archiveDesc = [[MTLBinaryArchiveDescriptor alloc] init]; archiveDesc.url = [NSURL fileURLWithPath:@(metalbin_path.c_str())]; @@ -695,6 +697,9 @@ void MetalKernelPipeline::compile() metal_printf("Failed to save binary archive, error:\n%s\n", [[error localizedDescription] UTF8String]); } + else { + path_cache_kernel_mark_added_and_clear_old(metalbin_path); + } } } }; diff --git a/intern/cycles/util/path.cpp b/intern/cycles/util/path.cpp index 17cff2f2977..cb6b8d7a740 100644 --- a/intern/cycles/util/path.cpp +++ b/intern/cycles/util/path.cpp @@ -2,8 +2,11 @@ * Copyright 2011-2022 Blender Foundation */ #include "util/path.h" +#include "util/algorithm.h" +#include "util/map.h" #include "util/md5.h" #include "util/string.h" +#include "util/vector.h" #include <OpenImageIO/filesystem.h> #include <OpenImageIO/strutil.h> @@ -898,19 +901,54 @@ FILE *path_fopen(const string &path, const string &mode) #endif } -void path_cache_clear_except(const string &name, const set<string> &except) +/* LRU Cache for Kernels */ + +static void path_cache_kernel_mark_used(const string &path) { - string dir = path_user_get("cache"); + std::time_t current_time = std::time(nullptr); + OIIO::Filesystem::last_write_time(path, current_time); +} - if (path_exists(dir)) { - directory_iterator it(dir), it_end; +bool path_cache_kernel_exists_and_mark_used(const string &path) +{ + if (path_exists(path)) { + path_cache_kernel_mark_used(path); + return true; + } + else { + return false; + } +} - for (; it != it_end; ++it) { - string filename = path_filename(it->path()); +void path_cache_kernel_mark_added_and_clear_old(const string &new_path, + const size_t max_old_kernel_of_same_type) +{ + path_cache_kernel_mark_used(new_path); + + string dir = path_dirname(new_path); + if (!path_exists(dir)) { + return; + } + + /* Remove older kernels within the same directory. */ + directory_iterator it(dir), it_end; + vector<pair<std::time_t, string>> same_kernel_types; + + for (; it != it_end; ++it) { + const string &path = it->path(); + if (path == new_path) { + continue; + } + + std::time_t last_time = OIIO::Filesystem::last_write_time(path); + same_kernel_types.emplace_back(last_time, path); + } + + if (same_kernel_types.size() > max_old_kernel_of_same_type) { + sort(same_kernel_types.begin(), same_kernel_types.end()); - if (string_startswith(filename, name.c_str())) - if (except.find(filename) == except.end()) - path_remove(it->path()); + for (int i = 0; i < same_kernel_types.size() - max_old_kernel_of_same_type; i++) { + path_remove(same_kernel_types[i].second); } } } diff --git a/intern/cycles/util/path.h b/intern/cycles/util/path.h index 48b1fb65919..6d02267e182 100644 --- a/intern/cycles/util/path.h +++ b/intern/cycles/util/path.h @@ -55,8 +55,15 @@ bool path_remove(const string &path); /* source code utility */ string path_source_replace_includes(const string &source, const string &path); -/* cache utility */ -void path_cache_clear_except(const string &name, const set<string> &except); +/* Simple least-recently-used cache for kernels. + * + * Kernels of same type are cached in the same directory. + * Whenever a kernel is used, its last modified time is updated. + * When a new kernel is added to the cache, clear old entries of the same type (i.e. in the same + * directory). */ +bool path_cache_kernel_exists_and_mark_used(const string &path); +void path_cache_kernel_mark_added_and_clear_old(const string &path, + const size_t max_old_kernel_of_same_type = 5); CCL_NAMESPACE_END |