Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented readonly-/ramdb preloading #3078

Open
wants to merge 63 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
f3d255e
Implemented readonly-/ramdb reloading
DrizztDoUrden Jun 25, 2024
ef1edf7
Merge branch 'develop' into ddu/ram-db-preload
DrizztDoUrden Jun 25, 2024
6656c97
format
DrizztDoUrden Jun 25, 2024
979c10f
Merge branch 'ddu/ram-db-preload' of github.com:ROCm/MIOpen into ddu/…
DrizztDoUrden Jun 25, 2024
a1c01a7
Fixed incorrect handle initialization
DrizztDoUrden Jun 25, 2024
ab6c331
Fixed test crashes on GetPreloadedDb
DrizztDoUrden Jun 25, 2024
d71c76a
Fixed crash
DrizztDoUrden Jun 26, 2024
c9127e0
format
DrizztDoUrden Jun 26, 2024
1cf533e
changed std::async capture to parameters
DrizztDoUrden Jun 26, 2024
6d1d01f
changed task back to capture
DrizztDoUrden Jul 11, 2024
a006ad0
Merge remote-tracking branch 'origin/develop' into ddu/ram-db-preload
DrizztDoUrden Jul 11, 2024
066e628
fixed unused warning
DrizztDoUrden Jul 11, 2024
8f11a24
Merge remote-tracking branch 'origin/develop' into ddu/ram-db-preload
DrizztDoUrden Jul 17, 2024
2c1c1db
format
DrizztDoUrden Jul 23, 2024
0c37aa4
Merge branch 'develop' into ddu/ram-db-preload
DrizztDoUrden Jul 23, 2024
f8d8af2
Added fusion dbs to the preload system
DrizztDoUrden Jul 24, 2024
cf15583
Merge remote-tracking branch 'origin/develop' into ddu/ram-db-preload
DrizztDoUrden Jul 24, 2024
38cd835
Resolved comments
DrizztDoUrden Jul 30, 2024
973953d
format
DrizztDoUrden Jul 30, 2024
eeec306
Merge branch 'develop' into ddu/ram-db-preload
DrizztDoUrden Jul 30, 2024
3dd3bdd
Rearranged code a little
DrizztDoUrden Aug 6, 2024
b1c7641
Fixed setting db preload started flag at inapropriate time and revert…
DrizztDoUrden Aug 6, 2024
2627d09
Merge branch 'develop' into ddu/ram-db-preload
DrizztDoUrden Aug 6, 2024
ff1ae74
More complicated atomic street magic
DrizztDoUrden Aug 6, 2024
6e3af1b
Fixed warning
DrizztDoUrden Aug 6, 2024
174f3e2
More fixes to the shortcutting logic
DrizztDoUrden Aug 7, 2024
f78b741
updated which bases are actually preloaded
DrizztDoUrden Aug 7, 2024
3f37e5c
missing #endif
DrizztDoUrden Aug 7, 2024
47615f3
fixed lock
DrizztDoUrden Aug 7, 2024
56aa92d
Merge branch 'develop' into ddu/ram-db-preload
DrizztDoUrden Aug 7, 2024
8dbd05d
got rid of lambda capture just to be safe
DrizztDoUrden Aug 8, 2024
9fabadc
Moved static back inside of a function
DrizztDoUrden Aug 8, 2024
34e7cbb
changed atomics to be relaxed
DrizztDoUrden Aug 8, 2024
ca8cec0
merged remote
DrizztDoUrden Aug 8, 2024
2f31a7d
Added a test
DrizztDoUrden Aug 10, 2024
1d28a43
changed set_value to set_value_at_thread_exit in the test
DrizztDoUrden Aug 10, 2024
6a0bfdf
some consts
DrizztDoUrden Aug 10, 2024
71419b3
Added a test case with very basic usage and no synchronisation
DrizztDoUrden Aug 10, 2024
2684065
fixed missing dllexport warnings
DrizztDoUrden Aug 12, 2024
5f65755
Added waiting for the last db preload thread on destroying last handle
DrizztDoUrden Aug 12, 2024
be7ba18
format
DrizztDoUrden Aug 12, 2024
c8e3c72
Some cleanup
DrizztDoUrden Aug 12, 2024
3142f0c
Moved nolint to where it was before
DrizztDoUrden Aug 12, 2024
91ddf45
Changed waiting for remaining threads to be more explicit
DrizztDoUrden Aug 13, 2024
d1938b2
Don't need lock to start the thread
DrizztDoUrden Aug 13, 2024
ddf51bb
moved error checking around a little
DrizztDoUrden Aug 13, 2024
abce075
format
DrizztDoUrden Aug 13, 2024
476fda9
tidy fix
DrizztDoUrden Aug 14, 2024
2bc459a
Merge remote-tracking branch 'origin/develop' into ddu/ram-db-preload
DrizztDoUrden Aug 14, 2024
1d483af
Updated db_preload to stop thread on static variable destructor and t…
DrizztDoUrden Aug 21, 2024
09a5c5c
Merge remote-tracking branch 'origin/develop' into ddu/ram-db-preload
DrizztDoUrden Aug 21, 2024
a45e501
Merge branch 'develop' into ddu/ram-db-preload
DrizztDoUrden Aug 21, 2024
25e5a2f
fixed redundant copy
DrizztDoUrden Aug 21, 2024
9cba91c
Merge remote-tracking branch 'origin/develop' into ddu/ram-db-preload
DrizztDoUrden Sep 13, 2024
13254d5
Merge remote-tracking branch 'origin/develop' into ddu/ram-db-preload
DrizztDoUrden Sep 24, 2024
bd04cc1
Renamed tests in db_preload.cpp
DrizztDoUrden Sep 24, 2024
ff24e60
Merge branch 'develop' into ddu/ram-db-preload
junliume Sep 26, 2024
f0e03c6
Merge remote-tracking branch 'origin/develop' into ddu/ram-db-preload
DrizztDoUrden Oct 15, 2024
b114ce3
Fixed "leak" like in develop
DrizztDoUrden Oct 15, 2024
ded332d
Some cleanup:
DrizztDoUrden Oct 15, 2024
a084b7c
format
DrizztDoUrden Oct 15, 2024
5be64ce
fixed test build
DrizztDoUrden Oct 15, 2024
a03d9cd
Merge remote-tracking branch 'origin/develop' into ddu/ram-db-preload
DrizztDoUrden Oct 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,8 @@ set( MIOpen_Source
tensor_api.cpp
transformers_adam_w_api.cpp
seq_tensor.cpp
)
handle_common.cpp
db_preload.cpp)

if(MIOPEN_ENABLE_AI_KERNEL_TUNING OR MIOPEN_ENABLE_AI_IMMED_MODE_FALLBACK)
list(APPEND MIOpen_Source conv/heuristics/ai_heuristics.cpp)
Expand Down
177 changes: 177 additions & 0 deletions src/db_preload.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*******************************************************************************
*
* MIT License
*
* Copyright (c) 2024 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 <miopen/execution_context.hpp>
#include <miopen/ramdb.hpp>
#include <miopen/readonlyramdb.hpp>
#include <miopen/type_name.hpp>
#include <miopen/db_preload.hpp>

#include <miopen/config.h>

#include <atomic>
#include <chrono>
#include <execution>
#include <future>
#include <mutex>

namespace miopen {
MIOPEN_INTERNALS_EXPORT DbPreloadStates::~DbPreloadStates()
{
std::unique_lock<std::mutex> lock(mutex);

if(preload_thread && preload_thread->joinable())
{
preload_stoper.request_stop();
preload_thread->join();
}
}

auto GetDbPreloadStates() -> std::shared_ptr<DbPreloadStates>
{
static auto db_preload_states = std::make_shared<DbPreloadStates>();
return db_preload_states;
}

template <class Db>
auto DbPreloadStates::GetPreloadedDb(const fs::path& path) -> std::unique_ptr<Db>
{
std::unique_lock<std::mutex> lock{mutex, std::defer_lock};

// Mutex is need to ensure states.futures is not updated while we work
// so we skip locking if it no more writes can happen
const auto needs_lock = !started_loading.load(std::memory_order_relaxed);

if(needs_lock)
lock.lock();

auto it = futures.find(path);

if(it == futures.end())
return nullptr;

auto future = std::move(it->second);

if(needs_lock)
lock.unlock();

if(!future.valid())
MIOPEN_THROW(miopenStatusInternalError,
"Attempt to reload " + path.string() + " as " + get_type_name<Db>());

const auto start = std::chrono::high_resolution_clock::now();
auto ret = future.get();
const auto end = std::chrono::high_resolution_clock::now();
const auto time = end - start;
MIOPEN_LOG_I("GetPreloadedDb time waiting for the db: " << time.count() * .000001f << " ms");
return std::get<std::unique_ptr<Db>>(std::move(ret));
}

template <class Db>
auto MakeDbPreloader(DbKinds db_kind, bool is_system) -> DbPreloader
{
if constexpr(std::is_same_v<Db, RamDb>)
{
return [=](const stop_token& stop, const fs::path& path) -> PreloadedDb {
auto db = std::make_unique<RamDb>(db_kind, path, is_system);
auto lock = std::unique_lock<LockFile>(db->GetLockFile(), GetDbLockTimeout());
if(!lock)
MIOPEN_THROW("Db lock has failed to lock.");
db->Prefetch(stop);
return {std::move(db)};
};
}
else
{
std::ignore = is_system;

return [=](const stop_token& stop, const fs::path& path) -> PreloadedDb {
auto db = std::make_unique<Db>(db_kind, path);
db->Prefetch(true, stop);
return {std::move(db)};
};
}
}

template auto MakeDbPreloader<RamDb>(DbKinds db_kind, bool is_system) -> DbPreloader;
template auto MakeDbPreloader<ReadonlyRamDb>(DbKinds db_kind, bool is_system) -> DbPreloader;

MIOPEN_INTERNALS_EXPORT void DbPreloadStates::StartPreloadingDb(const fs::path& path,
DbPreloader&& preloader)
{
if(path.empty())
return;

auto& task =
preload_tasks.emplace_back(std::bind(std::move(preloader), std::placeholders::_1, path));
futures.emplace(path, task.get_future());
}

MIOPEN_INTERNALS_EXPORT void
DbPreloadStates::TryStartPreloadingDbs(const std::function<void()>& preload)
{
if(started_loading.load(std::memory_order_relaxed))
return;

std::unique_lock<std::mutex> lock(mutex);

if(started_loading.load(std::memory_order_relaxed))
return;

preload();

started_loading.store(true, std::memory_order_relaxed);
// We have finished updating the map and can allow short-cutting the mutex

if(!preload_tasks.empty())
{
preload_stoper = stop_source();

preload_thread = std::thread(
[tasks = std::move(preload_tasks), token = preload_stoper.get_token()]() mutable {
MIOPEN_LOG_I("DB preload thread started");
std::for_each(std::execution::par_unseq,
tasks.begin(),
tasks.end(),
[token](auto&& task) { task(token); });
MIOPEN_LOG_I("DB preload thread finished");
});
}
}

MIOPEN_INTERNALS_EXPORT auto DbPreloadStates::GetPreloadedRamDb(const fs::path& path)
-> std::unique_ptr<RamDb>
{
return GetPreloadedDb<RamDb>(path);
}

MIOPEN_INTERNALS_EXPORT auto DbPreloadStates::GetPreloadedReadonlyRamDb(const fs::path& path)
-> std::unique_ptr<ReadonlyRamDb>
{
return GetPreloadedDb<ReadonlyRamDb>(path);
}

} // namespace miopen
11 changes: 6 additions & 5 deletions src/handle_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ extern "C" miopenStatus_t miopenGetVersion(size_t* major, size_t* minor, size_t*

extern "C" miopenStatus_t miopenCreate(miopenHandle_t* handle)
{

return miopen::try_([&] {
auto& h = miopen::deref(handle);
h = new miopen::Handle();
auto& h = miopen::deref(handle);
auto ptr = std::make_unique<miopen::Handle>();
h = ptr.release();
});
}

Expand All @@ -83,8 +83,9 @@ extern "C" miopenStatus_t miopenCreateWithStream(miopenHandle_t* handle,
{

return miopen::try_([&] {
auto& h = miopen::deref(handle);
h = new miopen::Handle(stream);
auto& h = miopen::deref(handle);
auto ptr = std::make_unique<miopen::Handle>(stream);
h = ptr.release();
});
}

Expand Down
82 changes: 82 additions & 0 deletions src/handle_common.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*******************************************************************************
*
* MIT License
*
* Copyright (c) 2024 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 <miopen/handle.hpp>

#include <miopen/db_preload.hpp>
#include <miopen/errors.hpp>
#include <miopen/find_db.hpp>
#include <miopen/mlo_internal.hpp>
#include <miopen/ramdb.hpp>
#include <miopen/readonlyramdb.hpp>

namespace miopen {
namespace {
void PreloadDbPair(DbPreloadStates* states, DbKinds kind, fs::path&& system, fs::path&& user)
{
#if !MIOPEN_DISABLE_SYSDB
states->StartPreloadingDb(system, MakeDbPreloader<ReadonlyRamDb>(kind, true));
#endif
#if !MIOPEN_DISABLE_USERDB
states->StartPreloadingDb(user, MakeDbPreloader<RamDb>(kind, false));
#endif
}
} // namespace

void Handle::TryStartPreloadingDbs()
{
auto const states = GetDbPreloadStates();

states->TryStartPreloadingDbs([&]() {
ExecutionContext ctx{this};

MIOPEN_LOG_I("Preloading dbs");

// conv find-db
PreloadDbPair(states.get(),
DbKinds::FindDb,
FindDbRecord::GetInstalledPath(*this, ""),
FindDbRecord::GetUserPath(*this, ""));

// fusion find-db
// it uses perf-db from convolution
PreloadDbPair(states.get(),
DbKinds::FindDb,
FindDbRecord::GetInstalledPath(*this, "fusion"),
FindDbRecord::GetUserPath(*this, "fusion"));

// conv perf-db
PreloadDbPair(states.get(), DbKinds::PerfDb, ctx.GetPerfDbPath(), ctx.GetUserPerfDbPath());

// batchnorm perf-db
// it doesn't use find-db
PreloadDbPair(states.get(),
DbKinds::PerfDb,
ctx.GetPerfDbPath("batchnorm"),
ctx.GetUserPerfDbPath("batchnorm"));
});
}
} // namespace miopen
6 changes: 6 additions & 0 deletions src/hip/handlehip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,9 @@ Handle::Handle(miopenAcceleratorQueue_t stream) : impl(std::make_unique<HandleIm
this->impl->hip_blasLt_handle = CreateHipblasLtHandle();
#endif
this->impl->target_properties.Init(this);

TryStartPreloadingDbs();

MIOPEN_LOG_NQI(*this);
}

Expand Down Expand Up @@ -340,6 +343,9 @@ Handle::Handle() : impl(std::make_unique<HandleImpl>())
this->impl->hip_blasLt_handle = CreateHipblasLtHandle();
#endif
this->impl->target_properties.Init(this);

TryStartPreloadingDbs();

MIOPEN_LOG_NQI(*this);
}

Expand Down
Loading
Loading