Skip to content

Commit af3e5b7

Browse files
GregoryComerfacebook-github-bot
authored andcommitted
(WIP) Refactor XNN workspace sharing to allow runtime gating (#11748)
Summary: Refactor the XNN backend workspace sharing logic to allow runtime gating. I've also added a temporary (marked experimental) API to enable workspace sharing. This will be replaced with backend options once available. Pull Request resolved: #11748 Test Plan: CI Rollback Plan: Differential Revision: D76789804 Pulled By: GregoryComer
1 parent 7503bb3 commit af3e5b7

File tree

4 files changed

+78
-47
lines changed

4 files changed

+78
-47
lines changed

backends/xnnpack/runtime/XNNCompiler.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,24 +1866,24 @@ ET_NODISCARD Error XNNCompiler::compileModel(
18661866
xnn_weights_cache_t weights_cache_ptr = nullptr;
18671867
#endif
18681868

1869-
#ifdef ENABLE_XNNPACK_SHARED_WORKSPACE
1870-
ET_CHECK_OR_RETURN_ERROR(
1871-
workspace != nullptr, Internal, "Failed to initialize XNNPACK workspace");
1872-
status = xnn_create_runtime_v4(
1873-
subgraph.get(),
1874-
weights_cache_ptr,
1875-
workspace,
1876-
::executorch::extension::threadpool::get_pthreadpool(),
1877-
runtime_flags,
1878-
&runtime_ptr);
1879-
#else
1880-
status = xnn_create_runtime_v3(
1881-
subgraph.get(),
1882-
weights_cache_ptr,
1883-
::executorch::extension::threadpool::get_pthreadpool(),
1884-
runtime_flags,
1885-
&runtime_ptr);
1886-
#endif
1869+
// NOLINTBEGIN(facebook-hte-NullableDereference) - weights cache is allowed to be null
1870+
if (workspace != nullptr) {
1871+
status = xnn_create_runtime_v4(
1872+
subgraph.get(),
1873+
weights_cache_ptr,
1874+
workspace,
1875+
::executorch::extension::threadpool::get_pthreadpool(),
1876+
runtime_flags,
1877+
&runtime_ptr);
1878+
} else {
1879+
status = xnn_create_runtime_v3(
1880+
subgraph.get(),
1881+
weights_cache_ptr,
1882+
::executorch::extension::threadpool::get_pthreadpool(),
1883+
runtime_flags,
1884+
&runtime_ptr);
1885+
}
1886+
// NOLINTEND(facebook-hte-NullableDereference)
18871887

18881888
ET_CHECK_OR_RETURN_ERROR(
18891889
xnn_status_success == status,

backends/xnnpack/runtime/XNNPACKBackend.cpp

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
#include <executorch/backends/xnnpack/runtime/XNNCompiler.h>
10+
#include <executorch/backends/xnnpack/runtime/XNNPACKBackend.h>
1011
#include <executorch/backends/xnnpack/runtime/XNNWeightsCache.h>
1112
#include <executorch/runtime/backend/interface.h>
1213
#include <executorch/runtime/core/error.h>
@@ -51,21 +52,9 @@ class XnnpackBackend final
5152
}
5253

5354
#ifdef ENABLE_XNNPACK_SHARED_WORKSPACE
54-
// Create a workspace for the XNNExecutor to use. This workspace will be
55-
// shared across all delegate instances.
56-
ET_LOG(Debug, "Creating XNN workspace");
57-
xnn_workspace_t workspace = nullptr;
58-
status = xnn_create_workspace(&workspace);
59-
if (status != xnn_status_success) {
60-
ET_LOG(
61-
Error,
62-
"Failed to create XNN workspace, XNNPACK status: 0x%x",
63-
(unsigned int)status);
64-
workspace = nullptr;
65-
return;
66-
}
67-
workspace_.reset(workspace);
68-
ET_LOG(Debug, "Created XNN workspace: %p", workspace_.get());
55+
enable_shared_workspace_ = true;
56+
#else
57+
enable_shared_workspace_ = false;
6958
#endif // ENABLE_XNNPACK_SHARED_WORKSPACE
7059
}
7160

@@ -86,9 +75,29 @@ class XnnpackBackend final
8675
const NamedDataMap* named_data_map = context.get_named_data_map();
8776
// thread safe. This can heppen when multiple threads call init() on
8877
// the same backend instance.
89-
#ifdef ENABLE_XNNPACK_SHARED_WORKSPACE
90-
const std::lock_guard<std::mutex> lock(workspace_mutex_);
91-
#endif
78+
79+
std::unique_lock<std::mutex> lock(workspace_mutex_, std::defer_lock);
80+
if (enable_shared_workspace_) {
81+
lock.lock();
82+
if (!workspace_) {
83+
// Create a workspace for the XNNExecutor to use. This workspace will be
84+
// shared across all delegate instances.
85+
ET_LOG(Debug, "Creating XNN workspace");
86+
xnn_workspace_t workspace = nullptr;
87+
auto status = xnn_create_workspace(&workspace);
88+
if (status != xnn_status_success) {
89+
ET_LOG(
90+
Error,
91+
"Failed to create XNN workspace, XNNPACK status: 0x%x",
92+
(unsigned int)status);
93+
workspace = nullptr;
94+
return Error::Internal;
95+
}
96+
// NOLINTNEXTLINE(facebook-hte-NullableDereference) - false positive
97+
workspace_.reset(workspace);
98+
ET_LOG(Debug, "Created XNN workspace: %p", workspace_.get());
99+
}
100+
}
92101

93102
#ifdef ENABLE_XNNPACK_WEIGHTS_CACHE
94103
const std::lock_guard<std::mutex> lock_weight_cache(weights_cache_mutex_);
@@ -129,9 +138,10 @@ class XnnpackBackend final
129138
EValue** args) const override {
130139
auto executor = static_cast<xnnpack::delegate::XNNExecutor*>(handle);
131140

132-
#ifdef ENABLE_XNNPACK_SHARED_WORKSPACE
133-
const std::lock_guard<std::mutex> lock(workspace_mutex_);
134-
#endif
141+
std::unique_lock<std::mutex> lock(workspace_mutex_, std::defer_lock);
142+
if (enable_shared_workspace_) {
143+
lock.lock();
144+
}
135145

136146
#ifdef ENABLE_XNNPACK_WEIGHTS_CACHE
137147
const std::lock_guard<std::mutex> lock_weights_cache(weights_cache_mutex_);
@@ -160,9 +170,10 @@ class XnnpackBackend final
160170
// This is needed to serialize access to xnn_delete_runtime which is not
161171
// thread safe. This can heppen when multiple threads call destroy() on
162172
// the same backend instance.
163-
#ifdef ENABLE_XNNPACK_SHARED_WORKSPACE
164-
const std::lock_guard<std::mutex> lock(workspace_mutex_);
165-
#endif
173+
std::unique_lock<std::mutex> lock(workspace_mutex_, std::defer_lock);
174+
if (enable_shared_workspace_) {
175+
lock.lock();
176+
}
166177

167178
auto executor = static_cast<xnnpack::delegate::XNNExecutor*>(handle);
168179

@@ -181,12 +192,16 @@ class XnnpackBackend final
181192
}
182193
}
183194

195+
void set_workspace_sharing_enabled(bool enable) {
196+
this->enable_shared_workspace_ = enable;
197+
}
198+
184199
private:
200+
bool enable_shared_workspace_;
185201
// This is a global workspace for all delegate instances.
186202
mutable std::mutex workspace_mutex_;
187-
std::unique_ptr<xnn_workspace, decltype(&xnn_release_workspace)> workspace_{
188-
nullptr,
189-
&xnn_release_workspace};
203+
mutable std::unique_ptr<xnn_workspace, decltype(&xnn_release_workspace)>
204+
workspace_{nullptr, &xnn_release_workspace};
190205

191206
// Weights cache is global to all delegate instances.
192207
mutable std::mutex weights_cache_mutex_;
@@ -199,10 +214,16 @@ class XnnpackBackend final
199214
};
200215

201216
namespace {
202-
auto cls = XnnpackBackend();
203-
Backend backend{"XnnpackBackend", &cls};
217+
auto backend_instance = XnnpackBackend();
218+
Backend backend{"XnnpackBackend", &backend_instance};
204219
static auto success_with_compiler = register_backend(backend);
205220
} // namespace
206221

222+
namespace xnnpack {
223+
void set_workspace_sharing_enabled(bool enable) {
224+
backend_instance.set_workspace_sharing_enabled(enable);
225+
}
226+
} // namespace xnnpack
227+
207228
} // namespace backends
208229
} // namespace executorch
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#pragma once
2+
3+
#include <executorch/runtime/platform/compiler.h>
4+
5+
namespace executorch::backends::xnnpack {
6+
ET_EXPERIMENTAL void set_workspace_sharing_enabled(bool enable);
7+
}

backends/xnnpack/targets.bzl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ def define_common_targets():
6161
exported_deps = [
6262
"//executorch/runtime/backend:interface" + aten_suffix,
6363
],
64+
exported_headers = [
65+
"runtime/XNNPACKBackend.h",
66+
],
6467
deps = [
6568
third_party_dep("XNNPACK"),
6669
"//executorch/backends/xnnpack/serialization:xnnpack_flatbuffer_header",

0 commit comments

Comments
 (0)