Skip to content

Commit 3ed0e10

Browse files
committed
Refactor XNN workspace sharing to allow runtime gating
1 parent 7b39a0c commit 3ed0e10

File tree

4 files changed

+71
-47
lines changed

4 files changed

+71
-47
lines changed

backends/xnnpack/runtime/XNNCompiler.cpp

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,24 +2237,22 @@ ET_NODISCARD Error XNNCompiler::compileModel(
22372237
xnn_weights_cache_t weights_cache_ptr = nullptr;
22382238
#endif
22392239

2240-
#ifdef ENABLE_XNNPACK_SHARED_WORKSPACE
2241-
ET_CHECK_OR_RETURN_ERROR(
2242-
workspace != nullptr, Internal, "Failed to initialize XNNPACK workspace");
2243-
status = xnn_create_runtime_v4(
2244-
subgraph.get(),
2245-
weights_cache_ptr,
2246-
workspace,
2247-
::executorch::extension::threadpool::get_pthreadpool(),
2248-
runtime_flags,
2249-
&runtime_ptr);
2250-
#else
2251-
status = xnn_create_runtime_v3(
2252-
subgraph.get(),
2253-
weights_cache_ptr,
2254-
::executorch::extension::threadpool::get_pthreadpool(),
2255-
runtime_flags,
2256-
&runtime_ptr);
2257-
#endif
2240+
if (workspace != nullptr) {
2241+
status = xnn_create_runtime_v4(
2242+
subgraph.get(),
2243+
weights_cache_ptr,
2244+
workspace,
2245+
::executorch::extension::threadpool::get_pthreadpool(),
2246+
runtime_flags,
2247+
&runtime_ptr);
2248+
} else {
2249+
status = xnn_create_runtime_v3(
2250+
subgraph.get(),
2251+
weights_cache_ptr,
2252+
::executorch::extension::threadpool::get_pthreadpool(),
2253+
runtime_flags,
2254+
&runtime_ptr);
2255+
}
22582256

22592257
ET_CHECK_OR_RETURN_ERROR(
22602258
xnn_status_success == status,

backends/xnnpack/runtime/XNNPACKBackend.cpp

Lines changed: 47 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,7 @@ 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;
6956
#endif // ENABLE_XNNPACK_SHARED_WORKSPACE
7057
}
7158

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

9399
#ifdef ENABLE_XNNPACK_WEIGHTS_CACHE
94100
const std::lock_guard<std::mutex> lock_weight_cache(weights_cache_mutex_);
@@ -129,9 +135,10 @@ class XnnpackBackend final
129135
EValue** args) const override {
130136
auto executor = static_cast<xnnpack::delegate::XNNExecutor*>(handle);
131137

132-
#ifdef ENABLE_XNNPACK_SHARED_WORKSPACE
133-
const std::lock_guard<std::mutex> lock(workspace_mutex_);
134-
#endif
138+
std::unique_lock<std::mutex> lock(workspace_mutex_, std::defer_lock);
139+
if (enable_shared_workspace_) {
140+
lock.lock();
141+
}
135142

136143
#ifdef ENABLE_XNNPACK_WEIGHTS_CACHE
137144
const std::lock_guard<std::mutex> lock_weights_cache(weights_cache_mutex_);
@@ -160,9 +167,10 @@ class XnnpackBackend final
160167
// This is needed to serialize access to xnn_delete_runtime which is not
161168
// thread safe. This can heppen when multiple threads call destroy() on
162169
// the same backend instance.
163-
#ifdef ENABLE_XNNPACK_SHARED_WORKSPACE
164-
const std::lock_guard<std::mutex> lock(workspace_mutex_);
165-
#endif
170+
std::unique_lock<std::mutex> lock(workspace_mutex_, std::defer_lock);
171+
if (enable_shared_workspace_) {
172+
lock.lock();
173+
}
166174

167175
auto executor = static_cast<xnnpack::delegate::XNNExecutor*>(handle);
168176

@@ -181,12 +189,16 @@ class XnnpackBackend final
181189
}
182190
}
183191

192+
void set_workspace_sharing_enabled(bool enable) {
193+
this->enable_shared_workspace_ = enable;
194+
}
195+
184196
private:
197+
bool enable_shared_workspace_;
185198
// This is a global workspace for all delegate instances.
186199
mutable std::mutex workspace_mutex_;
187-
std::unique_ptr<xnn_workspace, decltype(&xnn_release_workspace)> workspace_{
188-
nullptr,
189-
&xnn_release_workspace};
200+
mutable std::unique_ptr<xnn_workspace, decltype(&xnn_release_workspace)>
201+
workspace_{nullptr, &xnn_release_workspace};
190202

191203
// Weights cache is global to all delegate instances.
192204
mutable std::mutex weights_cache_mutex_;
@@ -199,10 +211,16 @@ class XnnpackBackend final
199211
};
200212

201213
namespace {
202-
auto cls = XnnpackBackend();
203-
Backend backend{"XnnpackBackend", &cls};
214+
auto backend_instance = XnnpackBackend();
215+
Backend backend{"XnnpackBackend", &backend_instance};
204216
static auto success_with_compiler = register_backend(backend);
205217
} // namespace
206218

219+
namespace executorch::backend::xnnpack {
220+
ET_EXPERIMENTAL void set_workspace_sharing_enabled(bool enable) {
221+
backend_instance.set_workspace_sharing_enabled(enable);
222+
}
223+
} // namespace executorch::backend::xnnpack
224+
207225
} // namespace backends
208226
} // namespace executorch
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include <executorch/runtime/compiler.h>
2+
3+
namespace executorch::backend::xnnpack {
4+
ET_EXPERIMENTAL void set_workspace_sharing_enabled(bool enable);
5+
}

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)