|
7 | 7 |
|
8 | 8 | #include <executorch/backends/xnnpack/runtime/XNNPACKBackend.h> |
9 | 9 |
|
| 10 | +#include <executorch/runtime/backend/backend_options_map.h> |
10 | 11 | #include <executorch/runtime/backend/interface.h> |
11 | 12 | #include <executorch/runtime/backend/options.h> |
12 | 13 | #include <executorch/runtime/executor/program.h> |
|
16 | 17 | #include <executorch/extension/memory_allocator/malloc_memory_allocator.h> |
17 | 18 | #include <executorch/extension/runner_util/inputs.h> |
18 | 19 |
|
| 20 | +using executorch::backends::xnnpack::weight_cache_option_key; |
19 | 21 | using executorch::backends::xnnpack::workspace_sharing_mode_option_key; |
20 | 22 | using executorch::backends::xnnpack::WorkspaceSharingMode; |
21 | 23 | using executorch::backends::xnnpack::xnnpack_backend_key; |
@@ -106,14 +108,17 @@ class ETPTEMethodRunBaseTest : public ::testing::Test { |
106 | 108 | } |
107 | 109 | }; |
108 | 110 |
|
109 | | -class XNNPACKMultiDelegateTest : public ETPTEMethodRunBaseTest { |
| 111 | +class XNNPACKMultiDelegateTest : public ETPTEMethodRunBaseTest, |
| 112 | + public ::testing::WithParamInterface< |
| 113 | + std::tuple<WorkspaceSharingMode, bool>> { |
110 | 114 | protected: |
111 | 115 | std::string kTestPTE1Path, kTestPTE2Path; |
112 | 116 | std::string kMethodName; |
113 | 117 | int num_threads; |
114 | 118 |
|
115 | 119 | void SetUp() override { |
116 | 120 | ETPTEMethodRunBaseTest::SetUp(); |
| 121 | + |
117 | 122 | const char* pte1_path = |
118 | 123 | std::getenv("ET_XNNPACK_GENERATED_ADD_LARGE_PTE_PATH"); |
119 | 124 | if (pte1_path == nullptr) { |
@@ -164,33 +169,64 @@ class XNNPACKMultiDelegateTest : public ETPTEMethodRunBaseTest { |
164 | 169 | ASSERT_EQ(count, num_threads); |
165 | 170 | } |
166 | 171 |
|
167 | | - void setWorkspaceSharingMode(WorkspaceSharingMode mode) { |
168 | | - executorch::runtime::runtime_init(); |
169 | | - |
170 | | - BackendOptions<1> backend_options; |
| 172 | + // Set both the workspace sharing mode and the weight cache flag in a single |
| 173 | + // call so each parameterized case starts from a clean, fully-specified |
| 174 | + // backend option state. set_option is process-global, and tests run |
| 175 | + // sequentially in the same process, so we must overwrite both options every |
| 176 | + // time to prevent leakage between cases. |
| 177 | + void setOptions(WorkspaceSharingMode mode, bool weight_cache_enabled) { |
| 178 | + BackendOptions<2> backend_options; |
171 | 179 | backend_options.set_option( |
172 | 180 | workspace_sharing_mode_option_key, static_cast<int>(mode)); |
| 181 | + backend_options.set_option(weight_cache_option_key, weight_cache_enabled); |
173 | 182 |
|
174 | 183 | auto status = executorch::runtime::set_option( |
175 | 184 | xnnpack_backend_key, backend_options.view()); |
176 | 185 | ASSERT_EQ(status, Error::Ok); |
177 | 186 | } |
178 | 187 | }; |
179 | 188 |
|
180 | | -TEST_F(XNNPACKMultiDelegateTest, MultipleThreadsSharingDisabled) { |
181 | | - setWorkspaceSharingMode(WorkspaceSharingMode::Disabled); |
182 | | - runStressTest(); |
183 | | -} |
184 | | - |
185 | | -TEST_F(XNNPACKMultiDelegateTest, MultipleThreadsPerModelSharing) { |
186 | | - setWorkspaceSharingMode(WorkspaceSharingMode::PerModel); |
| 189 | +// Parameterized over (WorkspaceSharingMode, weight_cache_enabled) to exercise |
| 190 | +// every combination of XNNPACK concurrency-affecting options. The |
| 191 | +// weight_cache_enabled=true cases reproduce the race condition fixed by |
| 192 | +// D105753995 (TSAN-detected data race on XNNWeightsCache::is_finalized_ / |
| 193 | +// named_data_map_ when init() is called concurrently). The |
| 194 | +// weight_cache_enabled=false cases provide regression coverage for the |
| 195 | +// non-cache concurrent path. |
| 196 | +TEST_P(XNNPACKMultiDelegateTest, MultipleThreadsStress) { |
| 197 | + const auto [sharing_mode, weight_cache_enabled] = GetParam(); |
| 198 | + setOptions(sharing_mode, weight_cache_enabled); |
187 | 199 | runStressTest(); |
188 | 200 | } |
189 | 201 |
|
190 | | -TEST_F(XNNPACKMultiDelegateTest, MultipleThreadsGlobalSharing) { |
191 | | - setWorkspaceSharingMode(WorkspaceSharingMode::Global); |
192 | | - runStressTest(); |
193 | | -} |
| 202 | +INSTANTIATE_TEST_SUITE_P( |
| 203 | + AllConfigs, |
| 204 | + XNNPACKMultiDelegateTest, |
| 205 | + ::testing::Combine( |
| 206 | + ::testing::Values( |
| 207 | + WorkspaceSharingMode::Disabled, |
| 208 | + WorkspaceSharingMode::PerModel, |
| 209 | + WorkspaceSharingMode::Global), |
| 210 | + ::testing::Bool()), |
| 211 | + [](const ::testing::TestParamInfo<XNNPACKMultiDelegateTest::ParamType>& |
| 212 | + info) { |
| 213 | + const auto sharing_mode = std::get<0>(info.param); |
| 214 | + const auto weight_cache_enabled = std::get<1>(info.param); |
| 215 | + const char* mode_name = "Unknown"; |
| 216 | + switch (sharing_mode) { |
| 217 | + case WorkspaceSharingMode::Disabled: |
| 218 | + mode_name = "SharingDisabled"; |
| 219 | + break; |
| 220 | + case WorkspaceSharingMode::PerModel: |
| 221 | + mode_name = "PerModelSharing"; |
| 222 | + break; |
| 223 | + case WorkspaceSharingMode::Global: |
| 224 | + mode_name = "GlobalSharing"; |
| 225 | + break; |
| 226 | + } |
| 227 | + return std::string(mode_name) + |
| 228 | + (weight_cache_enabled ? "_WeightCacheOn" : "_WeightCacheOff"); |
| 229 | + }); |
194 | 230 |
|
195 | 231 | // TODO(T208989291): Add more tests here. For example, |
196 | 232 | // - PTEs with multiple methods |
|
0 commit comments