/******************************************************************************* * * MIT License * * Copyright (c) 2017 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #if MIOPEN_ENABLE_SQLITE #include #endif #include #include #include #include #include #include #include MIOPEN_DECLARE_ENV_VAR_BOOL(MIOPEN_DISABLE_CACHE) MIOPEN_DECLARE_ENV_VAR_STR(MIOPEN_CUSTOM_CACHE_DIR) namespace miopen { static fs::path ComputeSysCachePath() { auto p = miopen::ExpandUser(GetSystemDbPath()); if(!fs::exists(p)) p.clear(); return p; } static fs::path ComputeUserCachePath() { #ifdef MIOPEN_CACHE_DIR fs::path p; /// If MIOPEN_CUSTOM_CACHE_DIR is set in the environment, then /// use exactly that path. const auto& custom = env::value(MIOPEN_CUSTOM_CACHE_DIR); const std::string cache_dir = !custom.empty() ? custom : MIOPEN_CACHE_DIR; const std::string version = std::to_string(MIOPEN_VERSION_MAJOR) // + "." + std::to_string(MIOPEN_VERSION_MINOR) // + "." + std::to_string(MIOPEN_VERSION_PATCH) // + "." + MIOPEN_STRINGIZE(MIOPEN_VERSION_TWEAK); p = miopen::ExpandUser(cache_dir) / version; #if !MIOPEN_BUILD_DEV /// \ref nfs-detection if(GetFilesystemChecker().IsNetworkedFilesystem(p) && custom.empty()) // Only if env variable isn't set { p = fs::temp_directory_path() / ".cache" / "miopen" / version; } #endif if(!fs::exists(p) && !MIOPEN_DISABLE_USERDB) fs::create_directories(p); return p; #else return {}; #endif } namespace { // Use static local variables to avoid non-const globals while allowing reset for testing const fs::path*& UserCachePathPtrRef() { static const fs::path* ptr = nullptr; return ptr; } const fs::path*& SysCachePathPtrRef() { static const fs::path* ptr = nullptr; return ptr; } const fs::path& GetUserCachePathInternal() { auto& ptr = UserCachePathPtrRef(); if(ptr == nullptr) ptr = new fs::path(ComputeUserCachePath()); return *ptr; } const fs::path& GetSysCachePathInternal() { auto& ptr = SysCachePathPtrRef(); if(ptr == nullptr) ptr = new fs::path(ComputeSysCachePath()); return *ptr; } } // namespace fs::path GetCachePath(bool is_system) { if(is_system) { if(MIOPEN_DISABLE_SYSDB) return {}; else return GetSysCachePathInternal(); } else { if(MIOPEN_DISABLE_USERDB) return {}; else return GetUserCachePathInternal(); } } #ifdef MIOPEN_BUILD_TESTING namespace testing { void ResetCachedPaths() { delete UserCachePathPtrRef(); delete SysCachePathPtrRef(); UserCachePathPtrRef() = nullptr; SysCachePathPtrRef() = nullptr; } } // namespace testing #endif bool IsCacheDisabled() { #ifdef MIOPEN_CACHE_DIR if(MIOPEN_DISABLE_USERDB && MIOPEN_DISABLE_SYSDB) return true; else return env::enabled(MIOPEN_DISABLE_CACHE); #else return true; #endif } #if MIOPEN_ENABLE_SQLITE_KERN_CACHE using KDb = DbTimer>; KDb GetDb(const TargetProperties& target, size_t num_cu) { static const auto user_dir = ComputeUserCachePath(); static const auto sys_dir = ComputeSysCachePath(); fs::path user_path = user_dir / (Handle::GetDbBasename(target, num_cu) + ".ukdb"); fs::path sys_path = sys_dir / (Handle::GetDbBasename(target, num_cu) + ".kdb"); if(user_dir.empty()) user_path = user_dir; if(!fs::exists(sys_path)) sys_path = sys_dir / (target.DbId() + ".kdb"); #if !MIOPEN_EMBED_DB if(!fs::exists(sys_path)) sys_path = fs::path{}; #endif return {DbKinds::KernelDb, sys_path, user_path}; } #endif fs::path GetCacheFile(const std::string& device, const fs::path& name, const std::string& args) { const auto filename = make_object_file_name(name); return GetCachePath(false) / miopen::md5(device + ":" + args) / filename; } #if MIOPEN_ENABLE_SQLITE_KERN_CACHE std::vector LoadBinary(const TargetProperties& target, const size_t num_cu, const fs::path& name, const std::string& args) { if(miopen::IsCacheDisabled()) return {}; auto db = GetDb(target, num_cu); const auto filename = make_object_file_name(name); const KernelConfig cfg{filename, args, {}}; MIOPEN_LOG_I2("Loading binary for: " << filename << "; args: " << args); auto record = db.FindRecord(cfg); if(record) { MIOPEN_LOG_I2("Successfully loaded binary for: " << filename << "; args: " << args); return *record; } else { MIOPEN_LOG_I2("Unable to load binary for: " << filename << "; args: " << args); return {}; } } void SaveBinary(const std::vector& hsaco, const TargetProperties& target, const std::size_t num_cu, const fs::path& name, const std::string& args) { if(miopen::IsCacheDisabled()) return; auto db = GetDb(target, num_cu); const auto filename = make_object_file_name(name); KernelConfig cfg{filename, args, hsaco}; MIOPEN_LOG_I2("Saving binary for: " << filename << "; args: " << args); db.StoreRecord(cfg); } #else fs::path LoadBinary(const TargetProperties& target, const size_t num_cu, const fs::path& name, const std::string& args) { if(miopen::IsCacheDisabled()) return {}; (void)num_cu; auto f = GetCacheFile(target.DbId(), name, args); if(fs::exists(f)) { return f; } else { return {}; } } fs::path SaveBinary(const fs::path& binary_path, const TargetProperties& target, const fs::path& name, const std::string& args) { if(miopen::IsCacheDisabled()) { fs::remove(binary_path); return {}; } else { auto p = GetCacheFile(target.DbId(), name, args); fs::create_directories(p.parent_path()); fs::rename(binary_path, p); return p; } } #endif } // namespace miopen