// Copyright Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #pragma once #include #include #include #include #include namespace rocRoller { /** * [sizeBegin,sizeEnd): A range of values representing sizes of dimensions. * Returns the number of coordinates within that space, * i.e. the product of those values. */ template size_t CoordCount(SizeIter sizeBegin, SizeIter sizeEnd); /** * [sizeBegin,sizeEnd): A range of values representing sizes of dimensions. * Writes into [coordBegin:coordEnd) the coordinates numbered `num` within * a linearization of all coordinates with earlier values being * faster-moving. */ template void CoordNumbered( size_t num, CoordIter coordBegin, CoordIter coordEnd, SizeIter sizeBegin, SizeIter sizeEnd); /** * If [coordBegin, coordEnd) represents coordinate x within the * linearization, updates it to represent coordinate x+1. * * If [coordBegin, coordEnd) represents the last coordinate within the * linearization, it will be reset to all 0s and false will be returned. */ template bool IncrementCoord(CoordIter coordBegin, CoordIter coordEnd, SizeIter sizeBegin, SizeIter sizeEnd); /* * Describes a tensor including dimensions, memory layout, and data type. * Decoupled from any particular pointer value or memory location. */ class TensorDescriptor { public: TensorDescriptor(); template TensorDescriptor(DataType t, IterA sizesBegin, IterA sizesEnd, IterB stridesBegin, IterB stridesEnd, size_t offset = 0); template TensorDescriptor(DataType t, Iter sizesBegin, Iter sizesEnd, size_t offset = 0); /** * Allow directly specifying total number of elements instead of sizes */ TensorDescriptor(DataType t, std::initializer_list sizes, size_t offset = 0); TensorDescriptor(DataType t, std::vector sizes, size_t offset = 0); TensorDescriptor(DataType t, std::initializer_list sizes, std::initializer_list strides, size_t offset = 0); TensorDescriptor(DataType t, std::vector sizes, std::vector strides, size_t offset = 0); /** * Specialized constructor for 2-D tensor (i.e., matrix) */ TensorDescriptor(DataType t, std::array sizes, std::string const& transpose, size_t offset = 0); static TensorDescriptor ShuffledNoPadding(DataType t, std::vector sizes, std::vector dimOrder); static TensorDescriptor ShuffledNoPadding(DataType t, std::initializer_list sizes, std::vector dimOrder); static TensorDescriptor ShuffledNoPadding(DataType t, std::vector sizes, std::initializer_list dimOrder); static TensorDescriptor ShuffledNoPadding(DataType t, std::initializer_list sizes, std::initializer_list dimOrder); inline void calculate(); const size_t size(size_t index) const; const std::vector& sizes() const; const size_t stride(size_t index) const; const std::vector& strides() const; size_t offset() const; size_t dimensions() const; size_t totalLogicalElements() const; size_t totalAllocatedElements() const; size_t totalAllocatedBytes() const; size_t elementBytes() const; /** * Returns the number of elements of padding in the given dimension (0 if * unpadded). May be negative if stride is less than size */ int64_t dimensionPadding(size_t dim) const; /** * Collapses dimensions in the interval [begin, end). * * preconditions: * - end >= begin * - begin < dimensions() * - end <= dimensions() * - dimensions in the interval [begin, end-1) are not padded. * * postconditions: * - dimensions() is diminished by end-begin * - total elements (allocated and logical) remain the same * - dimension 'begin' is the product of all the dimensions in the interval * [begin, end). */ void collapseDims(size_t begin, size_t end); DataType dataType() const; bool operator==(const TensorDescriptor& rhs) const; bool operator!=(const TensorDescriptor& rhs) const; std::string toString() const; template inline size_t index(Container const& indices) const; template inline size_t index(std::initializer_list indices) const; template inline size_t index(Ts... is) const; inline bool incrementCoord(std::vector& coord, size_t firstDimension = 0) const; TensorDescriptor withNormalizedDimensions() const; friend std::ostream& operator<<(std::ostream& stream, const TensorDescriptor& t); static inline const size_t UseDefaultStride = -1; private: std::vector m_sizes; std::vector m_strides; size_t m_offset = 0; size_t m_totalLogicalElements = 0; size_t m_totalAllocatedElements = 0; DataType m_dataType = DataType::Float; }; template inline void setCommandTensorArg(rocRoller::CommandArguments& commandArgs, rocRoller::Operations::OperationTag const& tag, TensorDescriptor& desc, T value); template std::string writeTensor(std::vector const& data, TensorDescriptor desc); /** * `dst` and `src` must be two TensorDescriptors with the same data type * and dimension sizes (i.e. dst.sizes() == src.sizes()). They should have * different strides (or this function is a no-op). * * `input` must contain data arranged according to `src`. * * Returns `input` rearranged according to the strides in `dst`. */ template inline std::vector shuffleDims(std::vector const& input, TensorDescriptor const& dst, TensorDescriptor const& src); } #include "TensorDescriptor_impl.hpp"