diff options
author | Matthew Sloyan <matthew.sloyan@arm.com> | 2022-06-30 17:13:04 +0100 |
---|---|---|
committer | Nikhil Raj <nikhil.raj@arm.com> | 2022-07-27 15:52:10 +0100 |
commit | 2d213a759e68f753ef4696e02a8535f7edfe421d (patch) | |
tree | f4003d0a60e907937e04d96fc434c0bfac596f86 /src/backends/backendsCommon | |
parent | 28aa6691accfd78c5eb5c4356316220d0e82ddef (diff) | |
download | armnn-2d213a759e68f753ef4696e02a8535f7edfe421d.tar.gz |
IVGCVSW-6620 Update the async api to use ExecutionData
* ExecutionData holds a void* which can be assigned to data required
for execution in a backend. WorkingMemDescriptors are used in the Ref
backend which hold TensorHandles for inputs and outputs.
* Updated ExecuteAsync functions to take ExecutionData.
* Added CreateExecutionData and UpdateExectutionData to IBackendInternal.
* Streamlined experimental IWorkingMemHandle API by removing map related
function and unused m_workingMemDescriptorMap from WorkingMemHandle.
Signed-off-by: Matthew Sloyan <matthew.sloyan@arm.com>
Change-Id: I54b0aab12872011743a141eb42dae200227769af
Diffstat (limited to 'src/backends/backendsCommon')
4 files changed, 37 insertions, 20 deletions
diff --git a/src/backends/backendsCommon/MemCopyWorkload.cpp b/src/backends/backendsCommon/MemCopyWorkload.cpp index 09d0e6c7d1..3e0782aa80 100644 --- a/src/backends/backendsCommon/MemCopyWorkload.cpp +++ b/src/backends/backendsCommon/MemCopyWorkload.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -63,11 +63,14 @@ void CopyMemGenericWorkload::Execute() const } } -void CopyMemGenericWorkload::ExecuteAsync(WorkingMemDescriptor& descriptor) +void CopyMemGenericWorkload::ExecuteAsync(ExecutionData& executionData) { ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "CopyMemGeneric_Execute_WorkingMemDescriptor"); + + WorkingMemDescriptor* workingMemDescriptor = static_cast<WorkingMemDescriptor*>(executionData.m_Data); std::vector<TensorHandlePair> tensorHandlePairs; - GatherTensorHandlePairs(descriptor, tensorHandlePairs); + + GatherTensorHandlePairs(*workingMemDescriptor, tensorHandlePairs); auto copyFunc = [](void* dst, const void* src, size_t size) { diff --git a/src/backends/backendsCommon/MemSyncWorkload.cpp b/src/backends/backendsCommon/MemSyncWorkload.cpp index af68306557..79df2d23dc 100644 --- a/src/backends/backendsCommon/MemSyncWorkload.cpp +++ b/src/backends/backendsCommon/MemSyncWorkload.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -27,11 +27,13 @@ void SyncMemGenericWorkload::Execute() const m_TensorHandle->Unmap(); } -void SyncMemGenericWorkload::ExecuteAsync(WorkingMemDescriptor& descriptor) +void SyncMemGenericWorkload::ExecuteAsync(ExecutionData& executionData) { ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "SyncMemGeneric_Execute_WorkingMemDescriptor"); - descriptor.m_Inputs[0]->Map(true); - descriptor.m_Inputs[0]->Unmap(); + + WorkingMemDescriptor* workingMemDescriptor = static_cast<WorkingMemDescriptor*>(executionData.m_Data); + workingMemDescriptor->m_Inputs[0]->Map(true); + workingMemDescriptor->m_Inputs[0]->Unmap(); } } //namespace armnn diff --git a/src/backends/backendsCommon/MemSyncWorkload.hpp b/src/backends/backendsCommon/MemSyncWorkload.hpp index eb2651731c..df54a654c7 100644 --- a/src/backends/backendsCommon/MemSyncWorkload.hpp +++ b/src/backends/backendsCommon/MemSyncWorkload.hpp @@ -1,5 +1,5 @@ // -// Copyright © 2017 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #pragma once @@ -19,7 +19,7 @@ class SyncMemGenericWorkload : public BaseWorkload<MemSyncQueueDescriptor> public: SyncMemGenericWorkload(const MemSyncQueueDescriptor& descriptor, const WorkloadInfo& info); void Execute() const override; - void ExecuteAsync(WorkingMemDescriptor& descriptor) override; + void ExecuteAsync(ExecutionData& executionData) override; private: ITensorHandle* m_TensorHandle; diff --git a/src/backends/backendsCommon/test/DefaultAsyncExecuteTest.cpp b/src/backends/backendsCommon/test/DefaultAsyncExecuteTest.cpp index b1ee89ac3c..0863ee45ca 100644 --- a/src/backends/backendsCommon/test/DefaultAsyncExecuteTest.cpp +++ b/src/backends/backendsCommon/test/DefaultAsyncExecuteTest.cpp @@ -1,5 +1,5 @@ // -// Copyright © 2021 Arm Ltd and Contributors. All rights reserved. +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // @@ -46,13 +46,14 @@ struct Workload0 : BaseWorkload<ElementwiseUnaryQueueDescriptor> } } - void ExecuteAsync(WorkingMemDescriptor& desc) + void ExecuteAsync(ExecutionData& executionData) { - int* inVals = static_cast<int*>(desc.m_Inputs[0][0].Map()); - int* outVals = static_cast<int*>(desc.m_Outputs[0][0].Map()); + WorkingMemDescriptor* workingMemDescriptor = static_cast<WorkingMemDescriptor*>(executionData.m_Data); + int* inVals = static_cast<int*>(workingMemDescriptor->m_Inputs[0][0].Map()); + int* outVals = static_cast<int*>(workingMemDescriptor->m_Outputs[0][0].Map()); for (unsigned int i = 0; - i < desc.m_Inputs[0][0].GetShape().GetNumElements(); + i < workingMemDescriptor->m_Inputs[0][0].GetShape().GetNumElements(); ++i) { outVals[i] = inVals[i] + outVals[i]; @@ -147,7 +148,10 @@ TEST_CASE("TestAsyncExecute") workingMemDescriptor0.m_Inputs = std::vector<ITensorHandle*>{&asyncInput0}; workingMemDescriptor0.m_Outputs = std::vector<ITensorHandle*>{&asyncOutput0}; - workload0.get()->ExecuteAsync(workingMemDescriptor0); + ExecutionData executionData; + executionData.m_Data = &workingMemDescriptor0; + + workload0.get()->ExecuteAsync(executionData); // Inputs are also changed by the execute/executeAsync calls to make sure there is no interference with them ValidateTensor(workingMemDescriptor0.m_Outputs[0], expectedExecuteAsyncval); @@ -183,7 +187,10 @@ TEST_CASE("TestDefaultAsyncExecute") workingMemDescriptor.m_Inputs = std::vector<ITensorHandle*>{&asyncInput}; workingMemDescriptor.m_Outputs = std::vector<ITensorHandle*>{&asyncOutput}; - workload1.get()->ExecuteAsync(workingMemDescriptor); + ExecutionData executionData; + executionData.m_Data = &workingMemDescriptor; + + workload1.get()->ExecuteAsync(executionData); // workload1 has no AsyncExecute implementation and so should use the default workload AsyncExecute // implementation which will call workload1.Execute() in a thread safe manner @@ -225,6 +232,8 @@ TEST_CASE("TestDefaultAsyncExeuteWithThreads") workingMemDescriptor1.m_Inputs = std::vector<ITensorHandle*>{&asyncInput1}; workingMemDescriptor1.m_Outputs = std::vector<ITensorHandle*>{&asyncOutput1}; + ExecutionData executionData1; + executionData1.m_Data = &workingMemDescriptor1; ScopedTensorHandle asyncInput2(constInputTensor2); ScopedTensorHandle asyncOutput2(constOutputTensor2); @@ -233,16 +242,19 @@ TEST_CASE("TestDefaultAsyncExeuteWithThreads") workingMemDescriptor2.m_Inputs = std::vector<ITensorHandle*>{&asyncInput2}; workingMemDescriptor2.m_Outputs = std::vector<ITensorHandle*>{&asyncOutput2}; + ExecutionData executionData2; + executionData2.m_Data = &workingMemDescriptor2; + std::thread thread1 = std::thread([&]() { - workload.get()->ExecuteAsync(workingMemDescriptor1); - workload.get()->ExecuteAsync(workingMemDescriptor1); + workload.get()->ExecuteAsync(executionData1); + workload.get()->ExecuteAsync(executionData1); }); std::thread thread2 = std::thread([&]() { - workload.get()->ExecuteAsync(workingMemDescriptor2); - workload.get()->ExecuteAsync(workingMemDescriptor2); + workload.get()->ExecuteAsync(executionData2); + workload.get()->ExecuteAsync(executionData2); }); thread1.join(); |