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
This commit is contained in:
parent
6f6a0185f2
commit
2c596319a4
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
if (string_startswith(filename, name.c_str()))
|
||||
if (except.find(filename) == except.end())
|
||||
path_remove(it->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());
|
||||
|
||||
for (int i = 0; i < same_kernel_types.size() - max_old_kernel_of_same_type; i++) {
|
||||
path_remove(same_kernel_types[i].second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue