blob: 589d849fa89d1bfab3a788bf6cbfb85d510dcf12 [file] [log] [blame]
//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//
#pragma once
#include "TensorFwd.hpp"
#include "Types.hpp"
#include "Exceptions.hpp"
#include <array>
#include <initializer_list>
#include <vector>
namespace armnn
{
class TensorShape
{
public:
/// Empty (invalid) constructor.
TensorShape();
TensorShape(unsigned int numDimensions);
TensorShape(unsigned int numDimensions, const unsigned int* dimensionSizes);
TensorShape(std::initializer_list<unsigned int> dimensionSizeList);
TensorShape(const TensorShape& other);
TensorShape& operator=(const TensorShape& other);
unsigned int operator[](unsigned int i) const;
unsigned int& operator[](unsigned int i);
bool operator==(const TensorShape& other) const;
bool operator!=(const TensorShape& other) const;
unsigned int GetNumDimensions() const { return m_NumDimensions; }
unsigned int GetNumElements() const;
private:
std::array<unsigned int, MaxNumOfTensorDimensions> m_Dimensions;
unsigned int m_NumDimensions;
void CheckDimensionIndex(unsigned int i) const;
};
class TensorInfo
{
public:
/// Empty (invalid) constructor.
TensorInfo();
TensorInfo(const TensorShape& shape, DataType dataType,
float quantizationScale = 0.0f, int32_t quantizationOffset = 0);
TensorInfo(unsigned int numDimensions, const unsigned int* dimensionSizes, DataType dataType,
float quantizationScale = 0.0f, int32_t quantizationOffset = 0);
TensorInfo(const TensorInfo& other);
TensorInfo& operator=(const TensorInfo& other);
bool operator==(const TensorInfo& other) const;
bool operator!=(const TensorInfo& other) const;
const TensorShape& GetShape() const { return m_Shape; }
TensorShape& GetShape() { return m_Shape; }
void SetShape(const TensorShape& newShape) { m_Shape = newShape; }
unsigned int GetNumDimensions() const { return m_Shape.GetNumDimensions(); }
unsigned int GetNumElements() const { return m_Shape.GetNumElements(); }
DataType GetDataType() const { return m_DataType; }
void SetDataType(DataType type) { m_DataType = type; }
float GetQuantizationScale() const { return m_Quantization.m_Scale; }
int32_t GetQuantizationOffset() const { return m_Quantization.m_Offset; }
void SetQuantizationScale(float scale) { m_Quantization.m_Scale = scale; }
void SetQuantizationOffset(int32_t offset) { m_Quantization.m_Offset = offset; }
bool IsQuantized() const { return m_DataType == DataType::QuantisedAsymm8; }
unsigned int GetNumBytes() const;
private:
TensorShape m_Shape;
DataType m_DataType;
/// Scale and offset values are used for quantization.
struct Quantization
{
Quantization() : m_Scale(0.f), m_Offset(0) {}
bool operator==(const Quantization& o) const {return ((m_Scale == o.m_Scale) && (m_Offset == o.m_Offset));}
float m_Scale;
int32_t m_Offset;
} m_Quantization;
};
template<typename MemoryType>
class BaseTensor
{
public:
/// Empty (invalid) constructor.
BaseTensor();
/// Constructor from a raw memory pointer.
/// @param memoryArea - Region of CPU-addressable memory where tensor data will be stored. Must be valid while
/// workloads are on the fly. Tensor instances do not claim ownership of referenced memory regions, that is,
/// no attempt will be made by ArmNN to free these memory regions automatically.
BaseTensor(const TensorInfo& info, MemoryType memoryArea);
/// Tensors are copyable.
BaseTensor(const BaseTensor& other);
/// Tensors are copyable.
BaseTensor& operator=(const BaseTensor&);
const TensorInfo& GetInfo() const { return m_Info; }
TensorInfo& GetInfo() { return m_Info; }
const TensorShape& GetShape() const { return m_Info.GetShape(); }
TensorShape& GetShape() { return m_Info.GetShape(); }
DataType GetDataType() const { return m_Info.GetDataType(); }
unsigned int GetNumDimensions() const { return m_Info.GetNumDimensions(); }
unsigned int GetNumBytes() const { return m_Info.GetNumBytes(); }
unsigned int GetNumElements() const { return m_Info.GetNumElements(); }
MemoryType GetMemoryArea() const { return m_MemoryArea; }
protected:
// Protected destructor to stop users from making these
// (could still new one on the heap and then leak it...)
~BaseTensor() {}
MemoryType m_MemoryArea;
private:
TensorInfo m_Info;
};
/// A tensor defined by a TensorInfo (shape and data type) and a mutable backing store.
class Tensor : public BaseTensor<void*>
{
public:
/// Brings in the constructors and assignment operator.
using BaseTensor<void*>::BaseTensor;
};
/// A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
class ConstTensor : public BaseTensor<const void*>
{
public:
/// Brings in the constructors and assignment operator.
using BaseTensor<const void*>::BaseTensor;
ConstTensor() : BaseTensor<const void*>() {} // This needs to be redefined explicitly??
/// Can be implicitly constructed from non-const Tensor.
ConstTensor(const Tensor& other) : BaseTensor<const void*>(other.GetInfo(), other.GetMemoryArea()) {}
/// Constructor from a backing container.
/// @param container - An stl-like container type which implements data() and size() methods.
/// Presence of data() and size() is a strong indicator of the continuous memory layout of the container,
/// which is a requirement for Tensor data. Tensor instances do not claim ownership of referenced memory regions,
/// that is, no attempt will be made by ArmNN to free these memory regions automatically.
template < template<typename, typename...> class ContainerType, typename T, typename...ContainerArgs >
ConstTensor(const TensorInfo& info, const ContainerType<T, ContainerArgs...>& container)
: BaseTensor<const void*>(info, container.data())
{
if (container.size() * sizeof(T) != info.GetNumBytes())
{
throw InvalidArgumentException("Container size is not correct");
}
}
};
using InputTensors = std::vector<std::pair<LayerBindingId, class ConstTensor>>;
using OutputTensors = std::vector<std::pair<LayerBindingId, class Tensor>>;
} // namespace armnn