[Bf-blender-cvs] [2c596319a48] master: Cycles: Cache only up to 5 kernels of each type on Metal

Michael Jones noreply at git.blender.org
Fri Nov 11 19:10:31 CET 2022


Commit: 2c596319a4888aa40bfdf41f9ea5d446179141d0
Author: Michael Jones
Date:   Fri Nov 11 18:10:16 2022 +0000
Branches: master
https://developer.blender.org/rB2c596319a4888aa40bfdf41f9ea5d446179141d0

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

===================================================================

M	intern/cycles/device/metal/kernel.mm
M	intern/cycles/util/path.cpp
M	intern/cycles/util/path.h

===================================================================

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



More information about the Bf-blender-cvs mailing list