aboutsummaryrefslogtreecommitdiff
path: root/src/backends/reference
diff options
context:
space:
mode:
Diffstat (limited to 'src/backends/reference')
-rw-r--r--src/backends/reference/CMakeLists.txt2
-rw-r--r--src/backends/reference/RefBackend.cpp24
-rw-r--r--src/backends/reference/RefBackend.hpp7
-rw-r--r--src/backends/reference/RefTensorHandle.cpp55
-rw-r--r--src/backends/reference/RefTensorHandle.hpp12
-rw-r--r--src/backends/reference/RefTensorHandleFactory.cpp62
-rw-r--r--src/backends/reference/RefTensorHandleFactory.hpp54
-rw-r--r--src/backends/reference/backend.mk1
-rw-r--r--src/backends/reference/test/RefEndToEndTests.cpp72
-rw-r--r--src/backends/reference/test/RefTensorHandleTests.cpp52
10 files changed, 340 insertions, 1 deletions
diff --git a/src/backends/reference/CMakeLists.txt b/src/backends/reference/CMakeLists.txt
index 963e64379d..6852ab0b74 100644
--- a/src/backends/reference/CMakeLists.txt
+++ b/src/backends/reference/CMakeLists.txt
@@ -16,6 +16,8 @@ list(APPEND armnnRefBackend_sources
RefRegistryInitializer.cpp
RefWorkloadFactory.cpp
RefWorkloadFactory.hpp
+ RefTensorHandleFactory.hpp
+ RefTensorHandleFactory.cpp
)
add_library(armnnRefBackend OBJECT ${armnnRefBackend_sources})
diff --git a/src/backends/reference/RefBackend.cpp b/src/backends/reference/RefBackend.cpp
index 41438b0151..2b56416b31 100644
--- a/src/backends/reference/RefBackend.cpp
+++ b/src/backends/reference/RefBackend.cpp
@@ -7,6 +7,7 @@
#include "RefBackendId.hpp"
#include "RefWorkloadFactory.hpp"
#include "RefLayerSupport.hpp"
+#include "RefTensorHandleFactory.hpp"
#include <backendsCommon/IBackendContext.hpp>
#include <backendsCommon/IMemoryManager.hpp>
@@ -32,6 +33,16 @@ IBackendInternal::IWorkloadFactoryPtr RefBackend::CreateWorkloadFactory(
return std::make_unique<RefWorkloadFactory>(boost::polymorphic_pointer_downcast<RefMemoryManager>(memoryManager));
}
+IBackendInternal::IWorkloadFactoryPtr RefBackend::CreateWorkloadFactory(
+ class TensorHandleFactoryRegistry& tensorHandleFactoryRegistry) const
+{
+ auto memoryManager = std::make_shared<RefMemoryManager>();
+
+ tensorHandleFactoryRegistry.RegisterMemoryManager(memoryManager);
+
+ return std::make_unique<RefWorkloadFactory>(boost::polymorphic_pointer_downcast<RefMemoryManager>(memoryManager));
+}
+
IBackendInternal::IBackendContextPtr RefBackend::CreateBackendContext(const IRuntime::CreationOptions&) const
{
return IBackendContextPtr{};
@@ -62,4 +73,17 @@ OptimizationViews RefBackend::OptimizeSubgraphView(const SubgraphView& subgraph)
return optimizationViews;
}
+std::vector<ITensorHandleFactory::FactoryId> RefBackend::GetHandleFactoryPreferences() const
+{
+ return std::vector<ITensorHandleFactory::FactoryId> { RefTensorHandleFactory::GetIdStatic() };
+}
+
+void RefBackend::RegisterTensorHandleFactories(class TensorHandleFactoryRegistry& registry)
+{
+ auto memoryManager = std::make_shared<RefMemoryManager>();
+
+ registry.RegisterMemoryManager(memoryManager);
+ registry.RegisterFactory(std::make_unique<RefTensorHandleFactory>(memoryManager));
+}
+
} // namespace armnn
diff --git a/src/backends/reference/RefBackend.hpp b/src/backends/reference/RefBackend.hpp
index 06179bd939..86e8b4c7bb 100644
--- a/src/backends/reference/RefBackend.hpp
+++ b/src/backends/reference/RefBackend.hpp
@@ -23,12 +23,19 @@ public:
IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(
const IBackendInternal::IMemoryManagerSharedPtr& memoryManager = nullptr) const override;
+ IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(
+ class TensorHandleFactoryRegistry& tensorHandleFactoryRegistry) const override;
+
IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const override;
IBackendInternal::Optimizations GetOptimizations() const override;
IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override;
OptimizationViews OptimizeSubgraphView(const SubgraphView& subgraph) const override;
+
+ std::vector<ITensorHandleFactory::FactoryId> GetHandleFactoryPreferences() const override;
+
+ void RegisterTensorHandleFactories(class TensorHandleFactoryRegistry& registry) override;
};
} // namespace armnn
diff --git a/src/backends/reference/RefTensorHandle.cpp b/src/backends/reference/RefTensorHandle.cpp
index fe9310f423..59ccec6bac 100644
--- a/src/backends/reference/RefTensorHandle.cpp
+++ b/src/backends/reference/RefTensorHandle.cpp
@@ -11,7 +11,21 @@ RefTensorHandle::RefTensorHandle(const TensorInfo &tensorInfo, std::shared_ptr<R
m_TensorInfo(tensorInfo),
m_MemoryManager(memoryManager),
m_Pool(nullptr),
- m_UnmanagedMemory(nullptr)
+ m_UnmanagedMemory(nullptr),
+ m_ImportFlags(static_cast<MemorySourceFlags>(MemorySource::Undefined)),
+ m_Imported(false)
+{
+
+}
+
+RefTensorHandle::RefTensorHandle(const TensorInfo& tensorInfo, std::shared_ptr<RefMemoryManager> &memoryManager,
+ MemorySourceFlags importFlags)
+ : m_TensorInfo(tensorInfo),
+ m_MemoryManager(memoryManager),
+ m_Pool(nullptr),
+ m_UnmanagedMemory(nullptr),
+ m_ImportFlags(importFlags),
+ m_Imported(false)
{
}
@@ -86,4 +100,43 @@ void RefTensorHandle::CopyInFrom(const void* src)
memcpy(dest, src, m_TensorInfo.GetNumBytes());
}
+bool RefTensorHandle::Import(void* memory, MemorySource source)
+{
+
+ if (m_ImportFlags & static_cast<MemorySourceFlags>(source))
+ {
+ if (source == MemorySource::Malloc)
+ {
+ // Checks the 16 byte memory alignment.
+ if (reinterpret_cast<uint64_t>(memory) % 16)
+ {
+ return false;
+ }
+
+ // m_UnmanagedMemory not yet allocated.
+ if (!m_Imported && !m_UnmanagedMemory)
+ {
+ m_UnmanagedMemory = memory;
+ m_Imported = true;
+ return true;
+ }
+
+ // m_UnmanagedMemory initially allocated with Allocate().
+ if (!m_Imported && m_UnmanagedMemory)
+ {
+ return false;
+ }
+
+ // m_UnmanagedMemory previously imported.
+ if (m_Imported)
+ {
+ m_UnmanagedMemory = memory;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
}
diff --git a/src/backends/reference/RefTensorHandle.hpp b/src/backends/reference/RefTensorHandle.hpp
index ad47ee597f..6cde3263a0 100644
--- a/src/backends/reference/RefTensorHandle.hpp
+++ b/src/backends/reference/RefTensorHandle.hpp
@@ -17,6 +17,9 @@ class RefTensorHandle : public ITensorHandle
public:
RefTensorHandle(const TensorInfo& tensorInfo, std::shared_ptr<RefMemoryManager> &memoryManager);
+ RefTensorHandle(const TensorInfo& tensorInfo, std::shared_ptr<RefMemoryManager> &memoryManager,
+ MemorySourceFlags importFlags);
+
~RefTensorHandle();
virtual void Manage() override;
@@ -49,6 +52,13 @@ public:
return m_TensorInfo;
}
+ virtual MemorySourceFlags GetImportFlags() const override
+ {
+ return m_ImportFlags;
+ }
+
+ virtual bool Import(void* memory, MemorySource source) override;
+
private:
// Only used for testing
void CopyOutTo(void*) const override;
@@ -64,6 +74,8 @@ private:
std::shared_ptr<RefMemoryManager> m_MemoryManager;
RefMemoryManager::Pool* m_Pool;
mutable void *m_UnmanagedMemory;
+ MemorySourceFlags m_ImportFlags;
+ bool m_Imported;
};
}
diff --git a/src/backends/reference/RefTensorHandleFactory.cpp b/src/backends/reference/RefTensorHandleFactory.cpp
new file mode 100644
index 0000000000..c97a779cb3
--- /dev/null
+++ b/src/backends/reference/RefTensorHandleFactory.cpp
@@ -0,0 +1,62 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "RefTensorHandleFactory.hpp"
+#include "RefTensorHandle.hpp"
+
+#include <boost/core/ignore_unused.hpp>
+
+namespace armnn
+{
+
+using FactoryId = ITensorHandleFactory::FactoryId;
+
+const FactoryId& RefTensorHandleFactory::GetIdStatic()
+{
+ static const FactoryId s_Id(RefTensorHandleFactoryId());
+ return s_Id;
+}
+
+std::unique_ptr<ITensorHandle> RefTensorHandleFactory::CreateSubTensorHandle(ITensorHandle& parent,
+ TensorShape const& subTensorShape,
+ unsigned int const* subTensorOrigin) const
+{
+ boost::ignore_unused(parent, subTensorShape, subTensorOrigin);
+ return nullptr;
+}
+
+std::unique_ptr<ITensorHandle> RefTensorHandleFactory::CreateTensorHandle(const TensorInfo& tensorInfo) const
+{
+ return std::make_unique<RefTensorHandle>(tensorInfo, m_MemoryManager, m_ImportFlags);
+}
+
+std::unique_ptr<ITensorHandle> RefTensorHandleFactory::CreateTensorHandle(const TensorInfo& tensorInfo,
+ DataLayout dataLayout) const
+{
+ boost::ignore_unused(dataLayout);
+ return std::make_unique<RefTensorHandle>(tensorInfo, m_MemoryManager, m_ImportFlags);
+}
+
+const FactoryId& RefTensorHandleFactory::GetId() const
+{
+ return GetIdStatic();
+}
+
+bool RefTensorHandleFactory::SupportsSubTensors() const
+{
+ return false;
+}
+
+MemorySourceFlags RefTensorHandleFactory::GetExportFlags() const
+{
+ return m_ExportFlags;
+}
+
+MemorySourceFlags RefTensorHandleFactory::GetImportFlags() const
+{
+ return m_ImportFlags;
+}
+
+} // namespace armnn \ No newline at end of file
diff --git a/src/backends/reference/RefTensorHandleFactory.hpp b/src/backends/reference/RefTensorHandleFactory.hpp
new file mode 100644
index 0000000000..220e6fd0de
--- /dev/null
+++ b/src/backends/reference/RefTensorHandleFactory.hpp
@@ -0,0 +1,54 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "RefMemoryManager.hpp"
+
+#include <backendsCommon/ITensorHandleFactory.hpp>
+
+namespace armnn
+{
+
+constexpr const char * RefTensorHandleFactoryId() { return "Arm/Ref/TensorHandleFactory"; }
+
+class RefTensorHandleFactory : public ITensorHandleFactory
+{
+
+public:
+ RefTensorHandleFactory(std::shared_ptr<RefMemoryManager> mgr)
+ : m_MemoryManager(mgr),
+ m_ImportFlags(static_cast<MemorySourceFlags>(MemorySource::Malloc)),
+ m_ExportFlags(static_cast<MemorySourceFlags>(MemorySource::Malloc))
+ {}
+
+ std::unique_ptr<ITensorHandle> CreateSubTensorHandle(ITensorHandle& parent,
+ TensorShape const& subTensorShape,
+ unsigned int const* subTensorOrigin) const override;
+
+ std::unique_ptr<ITensorHandle> CreateTensorHandle(const TensorInfo& tensorInfo) const override;
+
+ std::unique_ptr<ITensorHandle> CreateTensorHandle(const TensorInfo& tensorInfo,
+ DataLayout dataLayout) const override;
+
+ static const FactoryId& GetIdStatic();
+
+ const FactoryId& GetId() const override;
+
+ bool SupportsSubTensors() const override;
+
+ MemorySourceFlags GetExportFlags() const override;
+
+ MemorySourceFlags GetImportFlags() const override;
+
+private:
+ mutable std::shared_ptr<RefMemoryManager> m_MemoryManager;
+ MemorySourceFlags m_ImportFlags;
+ MemorySourceFlags m_ExportFlags;
+
+};
+
+} // namespace armnn
+
diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk
index b212995ad1..a8df565947 100644
--- a/src/backends/reference/backend.mk
+++ b/src/backends/reference/backend.mk
@@ -14,6 +14,7 @@ BACKEND_SOURCES := \
RefTensorHandle.cpp \
RefWorkloadFactory.cpp \
RefRegistryInitializer.cpp \
+ RefTensorHandleFactory.cpp \
workloads/Activation.cpp \
workloads/BatchNormImpl.cpp \
workloads/BatchToSpaceNd.cpp \
diff --git a/src/backends/reference/test/RefEndToEndTests.cpp b/src/backends/reference/test/RefEndToEndTests.cpp
index f81f1a708f..31e9b339ec 100644
--- a/src/backends/reference/test/RefEndToEndTests.cpp
+++ b/src/backends/reference/test/RefEndToEndTests.cpp
@@ -322,6 +322,78 @@ BOOST_AUTO_TEST_CASE(TrivialMin)
BOOST_TEST(outputData[3] == 2);
}
+BOOST_AUTO_TEST_CASE(RefNoCopyWorkloads)
+{
+ using namespace armnn;
+
+ // Create runtime in which test will run
+ IRuntime::CreationOptions options;
+ IRuntimePtr runtime(armnn::IRuntime::Create(options));
+
+ // build up the structure of the network
+ INetworkPtr net(INetwork::Create());
+
+ IConnectableLayer* input = net->AddInputLayer(0);
+
+ NormalizationDescriptor descriptor;
+ IConnectableLayer* norm = net->AddNormalizationLayer(descriptor);
+
+ IConnectableLayer* output = net->AddOutputLayer(0);
+
+ input->GetOutputSlot(0).Connect(norm->GetInputSlot(0));
+ norm->GetOutputSlot(0).Connect(output->GetInputSlot(0));
+
+ input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 1 }, DataType::Float32));
+ norm->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 1 }, DataType::Float32));
+
+ // Optimize the network
+ IOptimizedNetworkPtr optNet = Optimize(*net, defaultBackends, runtime->GetDeviceSpec());
+
+ // Loads it into the runtime.
+ NetworkId netId;
+ runtime->LoadNetwork(netId, std::move(optNet));
+
+ // Creates structures for input & output
+ std::vector<float> inputData
+ {
+ 1.0f, 2.0f, 3.0f, 4.0f
+ };
+
+ std::vector<float> outputData(4);
+
+ InputTensors inputTensors
+ {
+ {0,armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), inputData.data())},
+ };
+ OutputTensors outputTensors
+ {
+ {0,armnn::Tensor(runtime->GetOutputTensorInfo(netId, 0), outputData.data())}
+ };
+
+ // The result of the inference is not important, just the fact that there
+ // should not be CopyMemGeneric workloads.
+ runtime->GetProfiler(netId)->EnableProfiling(true);
+
+ // Do the inference
+ runtime->EnqueueWorkload(netId, inputTensors, outputTensors);
+
+ // Retrieve the Profiler.Print() output to get the workload execution
+ ProfilerManager& profilerManager = armnn::ProfilerManager::GetInstance();
+ std::stringstream ss;
+ profilerManager.GetProfiler()->Print(ss);;
+ std::string dump = ss.str();
+
+ // Contains RefNormalizationWorkload
+ std::size_t found = dump.find("RefNormalizationWorkload");
+ BOOST_TEST(found != std::string::npos);
+ // Contains SyncMemGeneric
+ found = dump.find("SyncMemGeneric");
+ BOOST_TEST(found != std::string::npos);
+ // No contains CopyMemGeneric
+ found = dump.find("CopyMemGeneric");
+ BOOST_TEST(found == std::string::npos);
+}
+
BOOST_AUTO_TEST_CASE(RefEqualSimpleEndToEndTest)
{
const std::vector<uint8_t> expectedOutput({ 1, 1, 1, 1, 0, 0, 0, 0,
diff --git a/src/backends/reference/test/RefTensorHandleTests.cpp b/src/backends/reference/test/RefTensorHandleTests.cpp
index accf900975..19b669b42f 100644
--- a/src/backends/reference/test/RefTensorHandleTests.cpp
+++ b/src/backends/reference/test/RefTensorHandleTests.cpp
@@ -45,4 +45,56 @@ BOOST_AUTO_TEST_CASE(AcquireAndRelease)
memoryManager->Release();
}
+BOOST_AUTO_TEST_CASE(CheckSourceType)
+{
+ std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
+
+ TensorInfo info({1}, DataType::Float32);
+ RefTensorHandle handle(info, memoryManager, static_cast<unsigned int>(MemorySource::Malloc));
+
+ // This pointer will be deleted in the handle destructor
+ int* testPtr = new int(4);
+
+ // Not supported
+ BOOST_CHECK(!handle.Import(static_cast<void *>(testPtr), MemorySource::DmaBuf));
+
+ // Not supported
+ BOOST_CHECK(!handle.Import(static_cast<void *>(testPtr), MemorySource::DmaBufProtected));
+
+ // Supported
+ BOOST_CHECK(handle.Import(static_cast<void *>(testPtr), MemorySource::Malloc));
+}
+
+BOOST_AUTO_TEST_CASE(ReusePointer)
+{
+ std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
+
+ TensorInfo info({1}, DataType::Float32);
+ RefTensorHandle handle(info, memoryManager, static_cast<unsigned int>(MemorySource::Malloc));
+
+ // This pointer will be deleted in the handle destructor
+ int* testPtr = new int(4);
+
+ handle.Import(static_cast<void *>(testPtr), MemorySource::Malloc);
+
+ // Reusing previously Imported pointer
+ BOOST_CHECK(handle.Import(static_cast<void *>(testPtr), MemorySource::Malloc));
+}
+
+BOOST_AUTO_TEST_CASE(MisalignedPointer)
+{
+ std::shared_ptr<RefMemoryManager> memoryManager = std::make_shared<RefMemoryManager>();
+
+ TensorInfo info({2}, DataType::Float32);
+ RefTensorHandle handle(info, memoryManager, static_cast<unsigned int>(MemorySource::Malloc));
+
+ // Allocates a 2 int array
+ int* testPtr = new int[2];
+ int* misalignedPtr = testPtr + 1;
+
+ BOOST_CHECK(!handle.Import(static_cast<void *>(misalignedPtr), MemorySource::Malloc));
+
+ delete[] testPtr;
+}
+
BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file