|
9 | 9 | #include <executorch/backends/xnnpack/runtime/XNNExecutor.h> |
10 | 10 | #include <executorch/backends/xnnpack/runtime/XNNPACKBackend.h> |
11 | 11 | #include <executorch/backends/xnnpack/serialization/schema_generated.h> |
| 12 | +#include <executorch/extension/threadpool/threadpool.h> |
12 | 13 | #include <executorch/runtime/core/exec_aten/testing_util/tensor_factory.h> |
13 | 14 | #include <executorch/runtime/platform/runtime.h> |
14 | 15 | #include <flatbuffers/flatbuffers.h> |
@@ -205,6 +206,81 @@ TEST(XNNCompilerTest, Bf16BatchMatrixMultiplyOutputWithoutDims) { |
205 | 206 | backend->destroy(handle.get()); |
206 | 207 | } |
207 | 208 |
|
| 209 | +TEST(XNNCompilerTest, RuntimeKeepsItsThreadpoolAcrossReset) { |
| 210 | + runtime::runtime_init(); |
| 211 | + auto* backend = runtime::get_backend_class(xnnpack_backend_key); |
| 212 | + ASSERT_NE(backend, nullptr); |
| 213 | + auto* threadpool = extension::threadpool::get_threadpool(); |
| 214 | + struct RestoreThreadCount { |
| 215 | + extension::threadpool::ThreadPool* threadpool; |
| 216 | + uint32_t threads; |
| 217 | + ~RestoreThreadCount() { |
| 218 | + // @lint-ignore CLANGTIDY facebook-hte-Deprecated |
| 219 | + threadpool->_unsafe_reset_threadpool(threads); |
| 220 | + } |
| 221 | + } restore{threadpool, static_cast<uint32_t>(threadpool->get_thread_count())}; |
| 222 | + // @lint-ignore CLANGTIDY facebook-hte-Deprecated |
| 223 | + ASSERT_TRUE(threadpool->_unsafe_reset_threadpool(2)); |
| 224 | + |
| 225 | + flatbuffers::FlatBufferBuilder builder; |
| 226 | + std::vector<flatbuffers::Offset<fb_xnnpack::XValue>> values; |
| 227 | + for (uint32_t id = 0; id < 3; ++id) { |
| 228 | + const auto tensor = fb_xnnpack::CreateXNNTensorValue( |
| 229 | + builder, |
| 230 | + fb_xnnpack::XNNDatatype::xnn_datatype_fp32, |
| 231 | + 1, |
| 232 | + builder.CreateVector<uint32_t>({4}), |
| 233 | + 0, |
| 234 | + id, |
| 235 | + id == 2 ? XNN_VALUE_FLAG_EXTERNAL_OUTPUT |
| 236 | + : XNN_VALUE_FLAG_EXTERNAL_INPUT, |
| 237 | + id); |
| 238 | + values.push_back(fb_xnnpack::CreateXValue( |
| 239 | + builder, fb_xnnpack::XValueUnion::XNNTensorValue, tensor.Union())); |
| 240 | + } |
| 241 | + const auto add = fb_xnnpack::Create_XNNNode2x1(builder, 0, 1, 2); |
| 242 | + const auto node = fb_xnnpack::CreateXNode( |
| 243 | + builder, fb_xnnpack::XNodeUnion::XNNAdd, add.Union()); |
| 244 | + const auto graph = fb_xnnpack::CreateXNNGraph( |
| 245 | + builder, |
| 246 | + builder.CreateString("0"), |
| 247 | + builder.CreateVector(&node, 1), |
| 248 | + builder.CreateVector(values), |
| 249 | + 3, |
| 250 | + builder.CreateVector<uint32_t>({0, 1}), |
| 251 | + builder.CreateVector<uint32_t>({2})); |
| 252 | + fb_xnnpack::FinishXNNGraphBuffer(builder, graph); |
| 253 | + |
| 254 | + std::array<uint8_t, 4096> memory{}; |
| 255 | + runtime::MemoryAllocator allocator(memory.size(), memory.data()); |
| 256 | + runtime::BackendInitContext context(&allocator); |
| 257 | + runtime::FreeableBuffer processed( |
| 258 | + builder.GetBufferPointer(), builder.GetSize(), nullptr); |
| 259 | + auto handle = backend->init(context, &processed, {}); |
| 260 | + ASSERT_TRUE(handle.ok()); |
| 261 | + const std::weak_ptr<pthreadpool> loaded_with = |
| 262 | + extension::threadpool::get_shared_pthreadpool(); |
| 263 | + |
| 264 | + // @lint-ignore CLANGTIDY facebook-hte-Deprecated |
| 265 | + ASSERT_TRUE(threadpool->_unsafe_reset_threadpool(3)); |
| 266 | + ASSERT_FALSE(loaded_with.expired()); |
| 267 | + TensorFactory<executorch::aten::ScalarType::Float> tf; |
| 268 | + EValue a(tf.make({4}, {1, 2, 3, 4})); |
| 269 | + EValue b(tf.make({4}, {10, 20, 30, 40})); |
| 270 | + EValue out(tf.zeros({4})); |
| 271 | + std::array<EValue*, 3> args{&a, &b, &out}; |
| 272 | + runtime::BackendExecutionContext execution_context; |
| 273 | + EXPECT_EQ( |
| 274 | + backend->execute(execution_context, handle.get(), {args.data(), 3}), |
| 275 | + Error::Ok); |
| 276 | + const float* sum = out.toTensor().const_data_ptr<float>(); |
| 277 | + EXPECT_EQ( |
| 278 | + std::vector<float>(sum, sum + 4), (std::vector<float>{11, 22, 33, 44})); |
| 279 | + |
| 280 | + backend->destroy(handle.get()); |
| 281 | + EXPECT_TRUE(loaded_with.expired()); |
| 282 | +} |
| 283 | + |
208 | 284 | } // namespace executorch::backends::xnnpack::delegate |
209 | 285 |
|
210 | 286 | TEST(XNNExecutorTest, ArgumentWithTooManyDimensions) { |
|
0 commit comments