xref: /aosp_15_r20/external/armnn/src/backends/backendsCommon/test/DefaultAsyncExecuteTest.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
3*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker 
6*89c4ff92SAndroid Build Coastguard Worker #include <armnn/Exceptions.hpp>
7*89c4ff92SAndroid Build Coastguard Worker 
8*89c4ff92SAndroid Build Coastguard Worker #include <armnn/backends/TensorHandle.hpp>
9*89c4ff92SAndroid Build Coastguard Worker #include <armnn/backends/Workload.hpp>
10*89c4ff92SAndroid Build Coastguard Worker 
11*89c4ff92SAndroid Build Coastguard Worker #include <doctest/doctest.h>
12*89c4ff92SAndroid Build Coastguard Worker 
13*89c4ff92SAndroid Build Coastguard Worker #include <thread>
14*89c4ff92SAndroid Build Coastguard Worker 
15*89c4ff92SAndroid Build Coastguard Worker using namespace armnn;
16*89c4ff92SAndroid Build Coastguard Worker 
17*89c4ff92SAndroid Build Coastguard Worker 
18*89c4ff92SAndroid Build Coastguard Worker namespace
19*89c4ff92SAndroid Build Coastguard Worker {
20*89c4ff92SAndroid Build Coastguard Worker 
21*89c4ff92SAndroid Build Coastguard Worker TEST_SUITE("WorkloadAsyncExecuteTests")
22*89c4ff92SAndroid Build Coastguard Worker {
23*89c4ff92SAndroid Build Coastguard Worker 
24*89c4ff92SAndroid Build Coastguard Worker struct Workload0 : BaseWorkload<ElementwiseUnaryQueueDescriptor>
25*89c4ff92SAndroid Build Coastguard Worker {
Workload0__anone931cbbc0111::Workload026*89c4ff92SAndroid Build Coastguard Worker     Workload0(const ElementwiseUnaryQueueDescriptor& descriptor, const WorkloadInfo& info)
27*89c4ff92SAndroid Build Coastguard Worker         : BaseWorkload(descriptor, info)
28*89c4ff92SAndroid Build Coastguard Worker     {
29*89c4ff92SAndroid Build Coastguard Worker     }
30*89c4ff92SAndroid Build Coastguard Worker 
Workload0__anone931cbbc0111::Workload031*89c4ff92SAndroid Build Coastguard Worker     Workload0() : BaseWorkload(ElementwiseUnaryQueueDescriptor(), WorkloadInfo())
32*89c4ff92SAndroid Build Coastguard Worker     {
33*89c4ff92SAndroid Build Coastguard Worker     }
34*89c4ff92SAndroid Build Coastguard Worker 
Execute__anone931cbbc0111::Workload035*89c4ff92SAndroid Build Coastguard Worker     void Execute() const
36*89c4ff92SAndroid Build Coastguard Worker     {
37*89c4ff92SAndroid Build Coastguard Worker         int* inVals = static_cast<int*>(m_Data.m_Inputs[0][0].Map());
38*89c4ff92SAndroid Build Coastguard Worker         int* outVals = static_cast<int*>(m_Data.m_Outputs[0][0].Map());
39*89c4ff92SAndroid Build Coastguard Worker 
40*89c4ff92SAndroid Build Coastguard Worker         for (unsigned int i = 0;
41*89c4ff92SAndroid Build Coastguard Worker              i < m_Data.m_Inputs[0][0].GetShape().GetNumElements();
42*89c4ff92SAndroid Build Coastguard Worker              ++i)
43*89c4ff92SAndroid Build Coastguard Worker         {
44*89c4ff92SAndroid Build Coastguard Worker             outVals[i] = inVals[i] * outVals[i];
45*89c4ff92SAndroid Build Coastguard Worker             inVals[i] = outVals[i];
46*89c4ff92SAndroid Build Coastguard Worker         }
47*89c4ff92SAndroid Build Coastguard Worker     }
48*89c4ff92SAndroid Build Coastguard Worker 
ExecuteAsync__anone931cbbc0111::Workload049*89c4ff92SAndroid Build Coastguard Worker     void ExecuteAsync(ExecutionData& executionData)
50*89c4ff92SAndroid Build Coastguard Worker     {
51*89c4ff92SAndroid Build Coastguard Worker         WorkingMemDescriptor* workingMemDescriptor = static_cast<WorkingMemDescriptor*>(executionData.m_Data);
52*89c4ff92SAndroid Build Coastguard Worker         int* inVals = static_cast<int*>(workingMemDescriptor->m_Inputs[0][0].Map());
53*89c4ff92SAndroid Build Coastguard Worker         int* outVals = static_cast<int*>(workingMemDescriptor->m_Outputs[0][0].Map());
54*89c4ff92SAndroid Build Coastguard Worker 
55*89c4ff92SAndroid Build Coastguard Worker         for (unsigned int i = 0;
56*89c4ff92SAndroid Build Coastguard Worker              i < workingMemDescriptor->m_Inputs[0][0].GetShape().GetNumElements();
57*89c4ff92SAndroid Build Coastguard Worker              ++i)
58*89c4ff92SAndroid Build Coastguard Worker         {
59*89c4ff92SAndroid Build Coastguard Worker             outVals[i] = inVals[i] + outVals[i];
60*89c4ff92SAndroid Build Coastguard Worker             inVals[i] = outVals[i];
61*89c4ff92SAndroid Build Coastguard Worker         }
62*89c4ff92SAndroid Build Coastguard Worker     }
63*89c4ff92SAndroid Build Coastguard Worker 
GetQueueDescriptor__anone931cbbc0111::Workload064*89c4ff92SAndroid Build Coastguard Worker     QueueDescriptor* GetQueueDescriptor()
65*89c4ff92SAndroid Build Coastguard Worker     {
66*89c4ff92SAndroid Build Coastguard Worker         return &m_Data;
67*89c4ff92SAndroid Build Coastguard Worker     }
68*89c4ff92SAndroid Build Coastguard Worker };
69*89c4ff92SAndroid Build Coastguard Worker 
70*89c4ff92SAndroid Build Coastguard Worker struct Workload1 : BaseWorkload<ElementwiseUnaryQueueDescriptor>
71*89c4ff92SAndroid Build Coastguard Worker {
Workload1__anone931cbbc0111::Workload172*89c4ff92SAndroid Build Coastguard Worker     Workload1(const ElementwiseUnaryQueueDescriptor& descriptor, const WorkloadInfo& info)
73*89c4ff92SAndroid Build Coastguard Worker         : BaseWorkload(descriptor, info)
74*89c4ff92SAndroid Build Coastguard Worker     {
75*89c4ff92SAndroid Build Coastguard Worker     }
76*89c4ff92SAndroid Build Coastguard Worker 
Execute__anone931cbbc0111::Workload177*89c4ff92SAndroid Build Coastguard Worker     void Execute() const
78*89c4ff92SAndroid Build Coastguard Worker     {
79*89c4ff92SAndroid Build Coastguard Worker         int* inVals = static_cast<int*>(m_Data.m_Inputs[0][0].Map());
80*89c4ff92SAndroid Build Coastguard Worker         int* outVals = static_cast<int*>(m_Data.m_Outputs[0][0].Map());
81*89c4ff92SAndroid Build Coastguard Worker 
82*89c4ff92SAndroid Build Coastguard Worker         for (unsigned int i = 0;
83*89c4ff92SAndroid Build Coastguard Worker              i < m_Data.m_Inputs[0][0].GetShape().GetNumElements();
84*89c4ff92SAndroid Build Coastguard Worker              ++i)
85*89c4ff92SAndroid Build Coastguard Worker         {
86*89c4ff92SAndroid Build Coastguard Worker             outVals[i] = inVals[i] * outVals[i];
87*89c4ff92SAndroid Build Coastguard Worker             inVals[i] = outVals[i];
88*89c4ff92SAndroid Build Coastguard Worker         }
89*89c4ff92SAndroid Build Coastguard Worker     }
90*89c4ff92SAndroid Build Coastguard Worker };
91*89c4ff92SAndroid Build Coastguard Worker 
ValidateTensor(ITensorHandle * tensorHandle,int expectedValue)92*89c4ff92SAndroid Build Coastguard Worker void ValidateTensor(ITensorHandle* tensorHandle, int expectedValue)
93*89c4ff92SAndroid Build Coastguard Worker {
94*89c4ff92SAndroid Build Coastguard Worker     int* actualOutput = static_cast<int*>(tensorHandle->Map());
95*89c4ff92SAndroid Build Coastguard Worker 
96*89c4ff92SAndroid Build Coastguard Worker     bool allValuesCorrect = true;
97*89c4ff92SAndroid Build Coastguard Worker     for (unsigned int i = 0;
98*89c4ff92SAndroid Build Coastguard Worker          i < tensorHandle->GetShape().GetNumElements();
99*89c4ff92SAndroid Build Coastguard Worker          ++i)
100*89c4ff92SAndroid Build Coastguard Worker     {
101*89c4ff92SAndroid Build Coastguard Worker         if (actualOutput[i] != expectedValue)
102*89c4ff92SAndroid Build Coastguard Worker         {
103*89c4ff92SAndroid Build Coastguard Worker             allValuesCorrect = false;
104*89c4ff92SAndroid Build Coastguard Worker         }
105*89c4ff92SAndroid Build Coastguard Worker     }
106*89c4ff92SAndroid Build Coastguard Worker 
107*89c4ff92SAndroid Build Coastguard Worker     CHECK(allValuesCorrect);
108*89c4ff92SAndroid Build Coastguard Worker }
109*89c4ff92SAndroid Build Coastguard Worker 
110*89c4ff92SAndroid Build Coastguard Worker template<typename Workload>
CreateWorkload(TensorInfo info,ITensorHandle * inputTensor,ITensorHandle * outputTensor)111*89c4ff92SAndroid Build Coastguard Worker std::unique_ptr<Workload> CreateWorkload(TensorInfo info, ITensorHandle* inputTensor, ITensorHandle* outputTensor)
112*89c4ff92SAndroid Build Coastguard Worker {
113*89c4ff92SAndroid Build Coastguard Worker     WorkloadInfo workloadInfo;
114*89c4ff92SAndroid Build Coastguard Worker     workloadInfo.m_InputTensorInfos = std::vector<TensorInfo>{info};
115*89c4ff92SAndroid Build Coastguard Worker     workloadInfo.m_OutputTensorInfos = std::vector<TensorInfo>{info};
116*89c4ff92SAndroid Build Coastguard Worker 
117*89c4ff92SAndroid Build Coastguard Worker     ElementwiseUnaryQueueDescriptor elementwiseUnaryQueueDescriptor;
118*89c4ff92SAndroid Build Coastguard Worker     elementwiseUnaryQueueDescriptor.m_Inputs = std::vector<ITensorHandle*>{inputTensor};
119*89c4ff92SAndroid Build Coastguard Worker     elementwiseUnaryQueueDescriptor.m_Outputs = std::vector<ITensorHandle*>{outputTensor};
120*89c4ff92SAndroid Build Coastguard Worker 
121*89c4ff92SAndroid Build Coastguard Worker     return std::make_unique<Workload>(elementwiseUnaryQueueDescriptor, workloadInfo);
122*89c4ff92SAndroid Build Coastguard Worker }
123*89c4ff92SAndroid Build Coastguard Worker 
124*89c4ff92SAndroid Build Coastguard Worker TEST_CASE("TestAsyncExecute")
125*89c4ff92SAndroid Build Coastguard Worker {
126*89c4ff92SAndroid Build Coastguard Worker     TensorInfo info({5}, DataType::Signed32, 0.0, 0, true);
127*89c4ff92SAndroid Build Coastguard Worker 
128*89c4ff92SAndroid Build Coastguard Worker     int inVals[5]{2, 2, 2, 2, 2};
129*89c4ff92SAndroid Build Coastguard Worker     int outVals[5]{1, 1, 1, 1, 1};
130*89c4ff92SAndroid Build Coastguard Worker 
131*89c4ff92SAndroid Build Coastguard Worker     int expectedExecuteval = 2;
132*89c4ff92SAndroid Build Coastguard Worker     int expectedExecuteAsyncval = 3;
133*89c4ff92SAndroid Build Coastguard Worker 
134*89c4ff92SAndroid Build Coastguard Worker     ConstTensor constInputTensor(info, inVals);
135*89c4ff92SAndroid Build Coastguard Worker     ConstTensor constOutputTensor(info, outVals);
136*89c4ff92SAndroid Build Coastguard Worker 
137*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle syncInput0(constInputTensor);
138*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle syncOutput0(constOutputTensor);
139*89c4ff92SAndroid Build Coastguard Worker 
140*89c4ff92SAndroid Build Coastguard Worker     std::unique_ptr<Workload0> workload0 = CreateWorkload<Workload0>(info, &syncInput0, &syncOutput0);
141*89c4ff92SAndroid Build Coastguard Worker 
142*89c4ff92SAndroid Build Coastguard Worker     workload0.get()->Execute();
143*89c4ff92SAndroid Build Coastguard Worker 
144*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle asyncInput0(constInputTensor);
145*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle asyncOutput0(constOutputTensor);
146*89c4ff92SAndroid Build Coastguard Worker 
147*89c4ff92SAndroid Build Coastguard Worker     WorkingMemDescriptor workingMemDescriptor0;
148*89c4ff92SAndroid Build Coastguard Worker     workingMemDescriptor0.m_Inputs = std::vector<ITensorHandle*>{&asyncInput0};
149*89c4ff92SAndroid Build Coastguard Worker     workingMemDescriptor0.m_Outputs = std::vector<ITensorHandle*>{&asyncOutput0};
150*89c4ff92SAndroid Build Coastguard Worker 
151*89c4ff92SAndroid Build Coastguard Worker     ExecutionData executionData;
152*89c4ff92SAndroid Build Coastguard Worker     executionData.m_Data = &workingMemDescriptor0;
153*89c4ff92SAndroid Build Coastguard Worker 
154*89c4ff92SAndroid Build Coastguard Worker     workload0.get()->ExecuteAsync(executionData);
155*89c4ff92SAndroid Build Coastguard Worker 
156*89c4ff92SAndroid Build Coastguard Worker     // Inputs are also changed by the execute/executeAsync calls to make sure there is no interference with them
157*89c4ff92SAndroid Build Coastguard Worker     ValidateTensor(workingMemDescriptor0.m_Outputs[0], expectedExecuteAsyncval);
158*89c4ff92SAndroid Build Coastguard Worker     ValidateTensor(workingMemDescriptor0.m_Inputs[0], expectedExecuteAsyncval);
159*89c4ff92SAndroid Build Coastguard Worker 
160*89c4ff92SAndroid Build Coastguard Worker     ValidateTensor(&workload0.get()->GetQueueDescriptor()->m_Outputs[0][0], expectedExecuteval);
161*89c4ff92SAndroid Build Coastguard Worker     ValidateTensor(&workload0.get()->GetQueueDescriptor()->m_Inputs[0][0], expectedExecuteval);
162*89c4ff92SAndroid Build Coastguard Worker }
163*89c4ff92SAndroid Build Coastguard Worker 
164*89c4ff92SAndroid Build Coastguard Worker TEST_CASE("TestDefaultAsyncExecute")
165*89c4ff92SAndroid Build Coastguard Worker {
166*89c4ff92SAndroid Build Coastguard Worker     TensorInfo info({5}, DataType::Signed32, 0.0f, 0, true);
167*89c4ff92SAndroid Build Coastguard Worker 
168*89c4ff92SAndroid Build Coastguard Worker     std::vector<int> inVals{2, 2, 2, 2, 2};
169*89c4ff92SAndroid Build Coastguard Worker     std::vector<int> outVals{1, 1, 1, 1, 1};
170*89c4ff92SAndroid Build Coastguard Worker     std::vector<int> defaultVals{0, 0, 0, 0, 0};
171*89c4ff92SAndroid Build Coastguard Worker 
172*89c4ff92SAndroid Build Coastguard Worker     int expectedExecuteval = 2;
173*89c4ff92SAndroid Build Coastguard Worker 
174*89c4ff92SAndroid Build Coastguard Worker     ConstTensor constInputTensor(info, inVals);
175*89c4ff92SAndroid Build Coastguard Worker     ConstTensor constOutputTensor(info, outVals);
176*89c4ff92SAndroid Build Coastguard Worker     ConstTensor defaultTensor(info, &defaultVals);
177*89c4ff92SAndroid Build Coastguard Worker 
178*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle defaultInput = ScopedTensorHandle(defaultTensor);
179*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle defaultOutput = ScopedTensorHandle(defaultTensor);
180*89c4ff92SAndroid Build Coastguard Worker 
181*89c4ff92SAndroid Build Coastguard Worker     std::unique_ptr<Workload1> workload1 = CreateWorkload<Workload1>(info, &defaultInput, &defaultOutput);
182*89c4ff92SAndroid Build Coastguard Worker 
183*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle asyncInput(constInputTensor);
184*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle asyncOutput(constOutputTensor);
185*89c4ff92SAndroid Build Coastguard Worker 
186*89c4ff92SAndroid Build Coastguard Worker     WorkingMemDescriptor workingMemDescriptor;
187*89c4ff92SAndroid Build Coastguard Worker     workingMemDescriptor.m_Inputs = std::vector<ITensorHandle*>{&asyncInput};
188*89c4ff92SAndroid Build Coastguard Worker     workingMemDescriptor.m_Outputs = std::vector<ITensorHandle*>{&asyncOutput};
189*89c4ff92SAndroid Build Coastguard Worker 
190*89c4ff92SAndroid Build Coastguard Worker     ExecutionData executionData;
191*89c4ff92SAndroid Build Coastguard Worker     executionData.m_Data = &workingMemDescriptor;
192*89c4ff92SAndroid Build Coastguard Worker 
193*89c4ff92SAndroid Build Coastguard Worker     workload1.get()->ExecuteAsync(executionData);
194*89c4ff92SAndroid Build Coastguard Worker 
195*89c4ff92SAndroid Build Coastguard Worker     // workload1 has no AsyncExecute implementation and so should use the default workload AsyncExecute
196*89c4ff92SAndroid Build Coastguard Worker     // implementation which will call  workload1.Execute() in a thread safe manner
197*89c4ff92SAndroid Build Coastguard Worker     ValidateTensor(workingMemDescriptor.m_Outputs[0], expectedExecuteval);
198*89c4ff92SAndroid Build Coastguard Worker     ValidateTensor(workingMemDescriptor.m_Inputs[0], expectedExecuteval);
199*89c4ff92SAndroid Build Coastguard Worker }
200*89c4ff92SAndroid Build Coastguard Worker 
201*89c4ff92SAndroid Build Coastguard Worker TEST_CASE("TestDefaultAsyncExeuteWithThreads")
202*89c4ff92SAndroid Build Coastguard Worker {
203*89c4ff92SAndroid Build Coastguard Worker     // Use a large vector so the threads have a chance to interact
204*89c4ff92SAndroid Build Coastguard Worker     unsigned int vecSize = 1000;
205*89c4ff92SAndroid Build Coastguard Worker     TensorInfo info({vecSize}, DataType::Signed32, 0.0f, 0, true);
206*89c4ff92SAndroid Build Coastguard Worker 
207*89c4ff92SAndroid Build Coastguard Worker     std::vector<int> inVals1(vecSize, 2);
208*89c4ff92SAndroid Build Coastguard Worker     std::vector<int> outVals1(vecSize, 1);
209*89c4ff92SAndroid Build Coastguard Worker     std::vector<int> inVals2(vecSize, 5);
210*89c4ff92SAndroid Build Coastguard Worker     std::vector<int> outVals2(vecSize, -1);
211*89c4ff92SAndroid Build Coastguard Worker 
212*89c4ff92SAndroid Build Coastguard Worker     std::vector<int> defaultVals(vecSize, 0);
213*89c4ff92SAndroid Build Coastguard Worker 
214*89c4ff92SAndroid Build Coastguard Worker     int expectedExecuteval1 = 4;
215*89c4ff92SAndroid Build Coastguard Worker     int expectedExecuteval2 = 25;
216*89c4ff92SAndroid Build Coastguard Worker     ConstTensor constInputTensor1(info, inVals1);
217*89c4ff92SAndroid Build Coastguard Worker     ConstTensor constOutputTensor1(info, outVals1);
218*89c4ff92SAndroid Build Coastguard Worker 
219*89c4ff92SAndroid Build Coastguard Worker     ConstTensor constInputTensor2(info, inVals2);
220*89c4ff92SAndroid Build Coastguard Worker     ConstTensor constOutputTensor2(info, outVals2);
221*89c4ff92SAndroid Build Coastguard Worker 
222*89c4ff92SAndroid Build Coastguard Worker     ConstTensor defaultTensor(info, defaultVals.data());
223*89c4ff92SAndroid Build Coastguard Worker 
224*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle defaultInput = ScopedTensorHandle(defaultTensor);
225*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle defaultOutput = ScopedTensorHandle(defaultTensor);
226*89c4ff92SAndroid Build Coastguard Worker     std::unique_ptr<Workload1> workload = CreateWorkload<Workload1>(info, &defaultInput, &defaultOutput);
227*89c4ff92SAndroid Build Coastguard Worker 
228*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle asyncInput1(constInputTensor1);
229*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle asyncOutput1(constOutputTensor1);
230*89c4ff92SAndroid Build Coastguard Worker 
231*89c4ff92SAndroid Build Coastguard Worker     WorkingMemDescriptor workingMemDescriptor1;
232*89c4ff92SAndroid Build Coastguard Worker     workingMemDescriptor1.m_Inputs = std::vector<ITensorHandle*>{&asyncInput1};
233*89c4ff92SAndroid Build Coastguard Worker     workingMemDescriptor1.m_Outputs = std::vector<ITensorHandle*>{&asyncOutput1};
234*89c4ff92SAndroid Build Coastguard Worker 
235*89c4ff92SAndroid Build Coastguard Worker     ExecutionData executionData1;
236*89c4ff92SAndroid Build Coastguard Worker     executionData1.m_Data = &workingMemDescriptor1;
237*89c4ff92SAndroid Build Coastguard Worker 
238*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle asyncInput2(constInputTensor2);
239*89c4ff92SAndroid Build Coastguard Worker     ScopedTensorHandle asyncOutput2(constOutputTensor2);
240*89c4ff92SAndroid Build Coastguard Worker 
241*89c4ff92SAndroid Build Coastguard Worker     WorkingMemDescriptor workingMemDescriptor2;
242*89c4ff92SAndroid Build Coastguard Worker     workingMemDescriptor2.m_Inputs = std::vector<ITensorHandle*>{&asyncInput2};
243*89c4ff92SAndroid Build Coastguard Worker     workingMemDescriptor2.m_Outputs = std::vector<ITensorHandle*>{&asyncOutput2};
244*89c4ff92SAndroid Build Coastguard Worker 
245*89c4ff92SAndroid Build Coastguard Worker     ExecutionData executionData2;
246*89c4ff92SAndroid Build Coastguard Worker     executionData2.m_Data = &workingMemDescriptor2;
247*89c4ff92SAndroid Build Coastguard Worker 
248*89c4ff92SAndroid Build Coastguard Worker     std::thread thread1 = std::thread([&]()
__anone931cbbc0202() 249*89c4ff92SAndroid Build Coastguard Worker                                       {
250*89c4ff92SAndroid Build Coastguard Worker                                           workload.get()->ExecuteAsync(executionData1);
251*89c4ff92SAndroid Build Coastguard Worker                                           workload.get()->ExecuteAsync(executionData1);
252*89c4ff92SAndroid Build Coastguard Worker                                       });
253*89c4ff92SAndroid Build Coastguard Worker 
254*89c4ff92SAndroid Build Coastguard Worker     std::thread thread2 = std::thread([&]()
__anone931cbbc0302() 255*89c4ff92SAndroid Build Coastguard Worker                                       {
256*89c4ff92SAndroid Build Coastguard Worker                                           workload.get()->ExecuteAsync(executionData2);
257*89c4ff92SAndroid Build Coastguard Worker                                           workload.get()->ExecuteAsync(executionData2);
258*89c4ff92SAndroid Build Coastguard Worker                                       });
259*89c4ff92SAndroid Build Coastguard Worker 
260*89c4ff92SAndroid Build Coastguard Worker     thread1.join();
261*89c4ff92SAndroid Build Coastguard Worker     thread2.join();
262*89c4ff92SAndroid Build Coastguard Worker 
263*89c4ff92SAndroid Build Coastguard Worker     ValidateTensor(workingMemDescriptor1.m_Outputs[0], expectedExecuteval1);
264*89c4ff92SAndroid Build Coastguard Worker     ValidateTensor(workingMemDescriptor1.m_Inputs[0], expectedExecuteval1);
265*89c4ff92SAndroid Build Coastguard Worker 
266*89c4ff92SAndroid Build Coastguard Worker     ValidateTensor(workingMemDescriptor2.m_Outputs[0], expectedExecuteval2);
267*89c4ff92SAndroid Build Coastguard Worker     ValidateTensor(workingMemDescriptor2.m_Inputs[0], expectedExecuteval2);
268*89c4ff92SAndroid Build Coastguard Worker }
269*89c4ff92SAndroid Build Coastguard Worker 
270*89c4ff92SAndroid Build Coastguard Worker }
271*89c4ff92SAndroid Build Coastguard Worker 
272*89c4ff92SAndroid Build Coastguard Worker }
273