|
5 | 5 | #include <thread>
|
6 | 6 | #include <vector>
|
7 | 7 |
|
| 8 | +#include <executorch/backends/xnnpack/runtime/XNNPACKBackend.h> |
| 9 | + |
| 10 | +#include <executorch/runtime/backend/interface.h> |
| 11 | +#include <executorch/runtime/backend/options.h> |
8 | 12 | #include <executorch/runtime/executor/program.h>
|
9 | 13 | #include <executorch/runtime/platform/runtime.h>
|
10 | 14 |
|
11 | 15 | #include <executorch/extension/data_loader/file_data_loader.h>
|
12 | 16 | #include <executorch/extension/memory_allocator/malloc_memory_allocator.h>
|
13 | 17 | #include <executorch/extension/runner_util/inputs.h>
|
14 | 18 |
|
| 19 | +using executorch::backends::xnnpack::workspace_sharing_mode_option_key; |
| 20 | +using executorch::backends::xnnpack::WorkspaceSharingMode; |
| 21 | +using executorch::backends::xnnpack::xnnpack_backend_key; |
| 22 | + |
| 23 | +using executorch::runtime::BackendOptions; |
15 | 24 | using executorch::runtime::Error;
|
16 | 25 | using executorch::runtime::EValue;
|
17 | 26 | using executorch::runtime::HierarchicalAllocator;
|
@@ -126,34 +135,61 @@ class XNNPACKMultiDelegateTest : public ETPTEMethodRunBaseTest {
|
126 | 135 | num_threads = 40;
|
127 | 136 | kMethodName = "forward";
|
128 | 137 | }
|
129 |
| -}; |
130 | 138 |
|
131 |
| -// This test is to validate the assumption that the delegate is thread safe. |
132 |
| -// That includes the following: |
133 |
| -// 1. The delegate can be initilized by multiple threads in parallel. |
134 |
| -// 2. The delegate can be executed by multiple threads in parallel. |
135 |
| -// 3. The delegate can be destroyed by multiple threads in parallel. |
136 |
| -// Regardless of the underlying implementation of the delegate. |
137 |
| -// This is particularly important when we have shared resources across |
138 |
| -// delegate instances through a singleton backend instance. |
139 |
| -TEST_F(XNNPACKMultiDelegateTest, MultipleThreads) { |
140 |
| - ASSERT_NE(kTestPTE1Path.size(), 0); |
141 |
| - ASSERT_NE(kTestPTE2Path.size(), 0); |
142 |
| - ASSERT_NE(num_threads, 0); |
143 |
| - ASSERT_NE(kMethodName.size(), 0); |
144 |
| - |
145 |
| - std::vector<std::thread> threads(num_threads); |
146 |
| - std::atomic<size_t> count{0}; |
147 |
| - |
148 |
| - for (int i = 0; i < num_threads; i++) { |
149 |
| - threads[i] = std::thread([&, i]() { |
150 |
| - run(i, i % 7 ? kTestPTE1Path : kTestPTE2Path, kMethodName, count); |
151 |
| - }); |
| 139 | + // This test is to validate the assumption that the delegate is thread safe. |
| 140 | + // That includes the following: |
| 141 | + // 1. The delegate can be initilized by multiple threads in parallel. |
| 142 | + // 2. The delegate can be executed by multiple threads in parallel. |
| 143 | + // 3. The delegate can be destroyed by multiple threads in parallel. |
| 144 | + // Regardless of the underlying implementation of the delegate. |
| 145 | + // This is particularly important when we have shared resources across |
| 146 | + // delegate instances through a singleton backend instance. |
| 147 | + void runStressTest() { |
| 148 | + ASSERT_NE(kTestPTE1Path.size(), 0); |
| 149 | + ASSERT_NE(kTestPTE2Path.size(), 0); |
| 150 | + ASSERT_NE(num_threads, 0); |
| 151 | + ASSERT_NE(kMethodName.size(), 0); |
| 152 | + |
| 153 | + std::vector<std::thread> threads(num_threads); |
| 154 | + std::atomic<size_t> count{0}; |
| 155 | + |
| 156 | + for (int i = 0; i < num_threads; i++) { |
| 157 | + threads[i] = std::thread([&, i]() { |
| 158 | + run(i, i % 7 ? kTestPTE1Path : kTestPTE2Path, kMethodName, count); |
| 159 | + }); |
| 160 | + } |
| 161 | + for (int i = 0; i < num_threads; i++) { |
| 162 | + threads[i].join(); |
| 163 | + } |
| 164 | + ASSERT_EQ(count, num_threads); |
152 | 165 | }
|
153 |
| - for (int i = 0; i < num_threads; i++) { |
154 |
| - threads[i].join(); |
| 166 | + |
| 167 | + void setWorkspaceSharingMode(WorkspaceSharingMode mode) { |
| 168 | + executorch::runtime::runtime_init(); |
| 169 | + |
| 170 | + BackendOptions<1> backend_options; |
| 171 | + backend_options.set_option( |
| 172 | + workspace_sharing_mode_option_key, static_cast<int>(mode)); |
| 173 | + |
| 174 | + auto status = executorch::runtime::set_option( |
| 175 | + xnnpack_backend_key, backend_options.view()); |
| 176 | + ASSERT_EQ(status, Error::Ok); |
155 | 177 | }
|
156 |
| - ASSERT_EQ(count, num_threads); |
| 178 | +}; |
| 179 | + |
| 180 | +TEST_F(XNNPACKMultiDelegateTest, MultipleThreadsSharingDisabled) { |
| 181 | + setWorkspaceSharingMode(WorkspaceSharingMode::Disabled); |
| 182 | + runStressTest(); |
| 183 | +} |
| 184 | + |
| 185 | +TEST_F(XNNPACKMultiDelegateTest, MultipleThreadsPerModelSharing) { |
| 186 | + setWorkspaceSharingMode(WorkspaceSharingMode::PerModel); |
| 187 | + runStressTest(); |
| 188 | +} |
| 189 | + |
| 190 | +TEST_F(XNNPACKMultiDelegateTest, MultipleThreadsGlobalSharing) { |
| 191 | + setWorkspaceSharingMode(WorkspaceSharingMode::Global); |
| 192 | + runStressTest(); |
157 | 193 | }
|
158 | 194 |
|
159 | 195 | // TODO(T208989291): Add more tests here. For example,
|
|
0 commit comments