1 2 // ================================================================================================= 3 // This file is part of the CLBlast project. The project is licensed under Apache Version 2.0. This 4 // project loosely follows the Google C++ styleguide and uses a tab-size of two spaces and a max- 5 // width of 100 characters per line. 6 // 7 // Author(s): 8 // Cedric Nugteren <www.cedricnugteren.nl> 9 // 10 // This file implements the caching functionality of compiled binaries and programs. 11 // 12 // ================================================================================================= 13 14 #ifndef CLBLAST_CACHE_H_ 15 #define CLBLAST_CACHE_H_ 16 17 #include <string> 18 #include <mutex> 19 #include <map> 20 21 #include "utilities/utilities.hpp" 22 23 namespace clblast { 24 // ================================================================================================= 25 26 // The generic thread-safe cache. We assume that the Key may be a heavyweight struct that is not 27 // normally used by the caller, while the Value is either lightweight or ref-counted. 28 // Hence, searching by non-Key is supported (if there is a corresponding operator<()), and 29 // on Store() the Key instance is moved from the caller (because it will likely be constructed 30 // as temporary at the time of Store()). 31 template <typename Key, typename Value> 32 class Cache { 33 public: 34 // Cached object is returned by-value to avoid racing with Invalidate(). 35 // Due to lack of std::optional<>, in case of a cache miss we return a default-constructed 36 // Value and set the flag to false. 37 template <typename U> 38 Value Get(const U &key, bool *in_cache) const; 39 40 // We do not return references to just stored object to avoid racing with Invalidate(). 41 // Caller is expected to store a temporary. 42 void Store(Key &&key, Value &&value); 43 void Invalidate(); 44 45 // Removes all entries with a given key 46 void Remove(const Key &key); 47 template <int I1, int I2> void RemoveBySubset(const Key &key); // currently supports 2 indices 48 49 static Cache<Key, Value> &Instance(); 50 51 private: 52 #if __cplusplus >= 201402L 53 // The std::less<void> allows to search in cache by an object comparable with Key, without 54 // constructing a temporary Key 55 // (see http://en.cppreference.com/w/cpp/utility/functional/less_void, 56 // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3657.htm, 57 // http://stackoverflow.com/questions/10536788/avoiding-key-construction-for-stdmapfind) 58 std::map<Key, Value, std::less<void>> cache_; 59 #else 60 std::vector<std::pair<Key, Value>> cache_; 61 #endif 62 mutable std::mutex cache_mutex_; 63 64 static Cache<Key, Value> instance_; 65 }; // class Cache 66 67 // ================================================================================================= 68 69 // The key struct for the cache of compiled OpenCL binaries 70 // Order of fields: precision, routine_name, device_name (smaller fields first) 71 typedef std::tuple<Precision, std::string, std::string> BinaryKey; 72 typedef std::tuple<const Precision &, const std::string &, const std::string &> BinaryKeyRef; 73 74 typedef Cache<BinaryKey, std::string> BinaryCache; 75 76 extern template class Cache<BinaryKey, std::string>; 77 extern template std::string BinaryCache::Get(const BinaryKeyRef &, bool *) const; 78 79 // ================================================================================================= 80 81 // The key struct for the cache of compiled OpenCL programs (context-dependent) 82 // Order of fields: context, device_id, precision, routine_name (smaller fields first) 83 typedef std::tuple<cl_context, cl_device_id, Precision, std::string> ProgramKey; 84 typedef std::tuple<const cl_context &, const cl_device_id &, const Precision &, const std::string &> ProgramKeyRef; 85 86 typedef Cache<ProgramKey, Program> ProgramCache; 87 88 extern template class Cache<ProgramKey, Program>; 89 extern template Program ProgramCache::Get(const ProgramKeyRef &, bool *) const; 90 91 // ================================================================================================= 92 93 class Database; 94 95 // The key struct for the cache of database maps. 96 // Order of fields: platform_id, device_id, precision, kernel_name (smaller fields first) 97 typedef std::tuple<cl_platform_id, cl_device_id, Precision, std::string> DatabaseKey; 98 typedef std::tuple<const cl_platform_id &, const cl_device_id &, const Precision &, const std::string &> DatabaseKeyRef; 99 100 typedef Cache<DatabaseKey, Database> DatabaseCache; 101 102 extern template class Cache<DatabaseKey, Database>; 103 extern template Database DatabaseCache::Get(const DatabaseKeyRef &, bool *) const; 104 105 // ================================================================================================= 106 } // namespace clblast 107 108 // CLBLAST_CACHE_H_ 109 #endif 110