diff options
Diffstat (limited to 'src/cache.hpp')
-rw-r--r-- | src/cache.hpp | 126 |
1 files changed, 67 insertions, 59 deletions
diff --git a/src/cache.hpp b/src/cache.hpp index 9ecb0f1e..c3675f07 100644 --- a/src/cache.hpp +++ b/src/cache.hpp @@ -15,81 +15,89 @@ #define CLBLAST_CACHE_H_ #include <string> -#include <vector> #include <mutex> +#include <map> #include "utilities/utilities.hpp" namespace clblast { // ================================================================================================= -// The cache of compiled OpenCL binaries, along with some meta-data -struct BinaryCache { - std::string binary; - std::string device_name; - Precision precision; - std::string routine_name_; - - // Finds out whether the properties match - bool MatchInCache(const std::string &ref_device, const Precision &ref_precision, - const std::string &ref_routine) { - return (device_name == ref_device && - precision == ref_precision && - routine_name_ == ref_routine); - } -}; - -// The actual cache, implemented as a vector of the above data-type, and its mutex -static std::vector<BinaryCache> binary_cache_; -static std::mutex binary_cache_mutex_; +// The generic thread-safe cache. We assume that the Key may be a heavyweight struct that is not +// normally used by the caller, while the Value is either lightweight or ref-counted. +// Hence, searching by non-Key is supported (if there is a corresponding operator<()), and +// on Store() the Key instance is moved from the caller (because it will likely be constructed +// as temporary at the time of Store()). +template <typename Key, typename Value> +class Cache { +public: + // Cached object is returned by-value to avoid racing with Invalidate(). + // Due to lack of std::optional<>, in case of a cache miss we return a default-constructed + // Value and set the flag to false. + template <typename U> + Value Get(const U &key, bool *in_cache) const; + + // We do not return references to just stored object to avoid racing with Invalidate(). + // Caller is expected to store a temporary. + void Store(Key &&key, Value &&value); + void Invalidate(); + + static Cache<Key, Value> &Instance(); + +private: +#if __cplusplus >= 201402L + // The std::less<void> allows to search in cache by an object comparable with Key, without + // constructing a temporary Key + // (see http://en.cppreference.com/w/cpp/utility/functional/less_void, + // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3657.htm, + // http://stackoverflow.com/questions/10536788/avoiding-key-construction-for-stdmapfind) + std::map<Key, Value, std::less<void>> cache_; +#else + std::vector<std::pair<Key, Value>> cache_; +#endif + mutable std::mutex cache_mutex_; + + static Cache<Key, Value> instance_; +}; // class Cache // ================================================================================================= -// The cache of compiled OpenCL programs, along with some meta-data -struct ProgramCache { - Program program; - cl_context context; - Precision precision; - std::string routine_name_; - - // Finds out whether the properties match - bool MatchInCache(const cl_context ref_context, const Precision &ref_precision, - const std::string &ref_routine) { - return (context == ref_context && - precision == ref_precision && - routine_name_ == ref_routine); - } -}; - -// The actual cache, implemented as a vector of the above data-type, and its mutex -static std::vector<ProgramCache> program_cache_; -static std::mutex program_cache_mutex_; +// The key struct for the cache of compiled OpenCL binaries +// Order of fields: precision, routine_name, device_name (smaller fields first) +typedef std::tuple<Precision, std::string, std::string> BinaryKey; +typedef std::tuple<const Precision &, const std::string &, const std::string &> BinaryKeyRef; + +typedef Cache<BinaryKey, std::string> BinaryCache; + +extern template class Cache<BinaryKey, std::string>; +extern template std::string BinaryCache::Get(const BinaryKeyRef &, bool *) const; + // ================================================================================================= -// Stores the compiled binary or program in the cache -void StoreBinaryToCache(const std::string &binary, const std::string &device_name, - const Precision &precision, const std::string &routine_name); -void StoreProgramToCache(const Program &program, const Context &context, - const Precision &precision, const std::string &routine_name); - -// Queries the cache and retrieves a matching binary or program. Assumes that the match is -// available, throws otherwise. -const std::string& GetBinaryFromCache(const std::string &device_name, const Precision &precision, - const std::string &routine_name); -const Program& GetProgramFromCache(const Context &context, const Precision &precision, - const std::string &routine_name); - -// Queries the cache to see whether or not the compiled kernel is already there -bool BinaryIsInCache(const std::string &device_name, const Precision &precision, - const std::string &routine_name); -bool ProgramIsInCache(const Context &context, const Precision &precision, - const std::string &routine_name); +// The key struct for the cache of compiled OpenCL programs (context-dependent) +// Order of fields: context, precision, routine_name (smaller fields first) +typedef std::tuple<cl_context, Precision, std::string> ProgramKey; +typedef std::tuple<const cl_context &, const Precision &, const std::string &> ProgramKeyRef; + +typedef Cache<ProgramKey, Program> ProgramCache; + +extern template class Cache<ProgramKey, Program>; +extern template Program ProgramCache::Get(const ProgramKeyRef &, bool *) const; // ================================================================================================= -// Clears the cache of stored binaries -void CacheClearAll(); +class Database; + +// The key struct for the cache of database maps. +// Order of fields: precision, device_name, routines (smaller fields first) +typedef std::tuple<Precision, std::string, std::vector<std::string>> DatabaseKey; +typedef std::tuple<const Precision &, const std::string &, const std::vector<std::string> &> DatabaseKeyRef; + +typedef Cache<DatabaseKey, Database> DatabaseCache; + +extern template class Cache<DatabaseKey, Database>; +extern template Database DatabaseCache::Get(const DatabaseKeyRef &, bool *) const; // ================================================================================================= } // namespace clblast |