Skip to content
Snippets Groups Projects
Commit dfd84975 authored by Olivier BICHLER's avatar Olivier BICHLER
Browse files

Merge branch 'improved_mem_doc' into 'dev'

Improved mem doc

See merge request !182
parents f410ee54 410c9c35
No related branches found
No related tags found
2 merge requests!212Version 0.3.0,!182Improved mem doc
Pipeline #53678 passed
......@@ -19,6 +19,25 @@
#include "aidge/graph/Node.hpp"
namespace Aidge {
/**
* @brief The MemoryManager can be used to generate an optimized static memory
* layout for a computing graph in a global memory space.
* The are some assumptions:
* - A MemoryManager represents a single global memory space, filled with
* contiguous, non-overlapping MemorySpace chunks.
* - A MemorySpace contains one or multiple MemoryPlane, each MemoryPlane
* corresponding to the allocation of a specific Tensor. When a Tensor can re-
* use the memory of the preceding one (for in-place or partially in-place
* operators), multiple overlapping MemoryPlane can be created in the same
* MemorySpace (remember, MemorySpace **cannot** be overlapping!).
* - A MemoryPlane is tailored for handling (N)HWC data with two properties:
* - Possibility of wrapping: on the H axis (each W*C block is contiguous).
* - Possibility of concatenation: on the C axis (C1+C2+...+Cn).
* - All the sizes and offets specified in a MemoryManager are expressed in
* number of data elements, or **words**, meaning currently a uniform data
* precision is expected in a MemoryManager (for instance, if the precision is
* 16-bits, each data element will be 2 bytes, which will be the size of a word).
*/
class MemoryManager {
public:
typedef int Clock_T;
......@@ -45,18 +64,45 @@ public:
allocated(clock_),
released(-1) {}
/// Offset of the MemorySpace in the MemoryManager global memory space (in words)
unsigned int offset;
/// Size of the MemorySpace (in words)
unsigned int size;
std::set<std::shared_ptr<Node> > dependencies;
Clock_T allocated;
Clock_T released;
};
// MemoryPlane belongs to a MemorySpace. Any number of potentially
// overlapping planes can be associated to a MemorySpace.
// MemoryPlane can be non-contiguous (in case of stride, or wrapping, when
// offset + size > memSpace.size).
// MemoryPlane cannot be re-arranged inside a MemorySpace.
/**
* @brief MemoryPlane belongs to a MemorySpace. Any number of potentiall
* overlapping planes can be associated to a MemorySpace.
* MemoryPlane can be non-contiguous (in case of stride, or wrapping, when
* offset + size > memSpace.size).
* MemoryPlane cannot be re-arranged inside a MemorySpace.
*
* A MemoryPlane is tailored for handling (N)HWC data with two properties:
* - Possibility of wrapping: on the H axis (each W*C block is contiguous).
* - Possibility of concatenation: on the C axis (C1+C2+...+Cn).
*
* Detail of (N)HWC data handling:
* - \p length is the size of contiguous and non-breakable memory line (W in HWC);
* - \p count is the number of memory lines of size \p length constituting a memory block (H in HWC);
* - \p stride is the number of channels, or memory blocks, *in total*,
* of \p count lines of size \p length (C in NHWC);
* - \p size is the number of channels, or memory blocks, *in this MemoryPlane*,
* of \p count lines of size \p length.
* In the case of concatenation, there can be multiple overlapping MemoryPlane
* with different size, like NHWC = NHW(C1+C2):
* - MemoryPlane#1: \p size = C1 and \p stride = C=C1+C2
* - MemoryPlane#2: \p size = C2 and \p stride = C=C1+C2
* (with an additionnal relative offset of +C1)
* In this mode, wrapping can only occur on the H (\p count) axis. W*C chunks
* are garanteed to be contiguous (\p length * \p stride).
*
* By default, \p stride = \p size, \p count = 1 and \p length = 1, meaning
* there is no NHWC layout and the MemoryPlane can be wrapped **anywhere**.
* In this case, \p size is the total size of the MemoryPlane (H*W*C, in words).
*/
struct MemoryPlane {
MemoryPlane(std::shared_ptr<MemorySpace> memSpace_,
Clock_T clock_,
......@@ -92,36 +138,91 @@ public:
<= memSpace->offset + memSpace->size);
}
/**
* @brief Get the total size of the MemoryPlane, including the stride.
*
* @return unsigned int Total size in words
*/
inline unsigned int getSize() const {
return stride * length * count;
}
/**
* @brief Get the useful size of the MemoryPlane, as if its memory blocks
* were contiguous, without stride.
*
* @return unsigned int Useful size in words
*/
inline unsigned int getUsefulSize() const {
return size * length * count;
}
/**
* @brief Get the absolute offset of the beginning of the memory plane.
*
* @return unsigned int Contiguous offset in words
*/
inline unsigned int getContiguousOffset() const {
return memSpace->offset + offset;
}
/**
* @brief Get the size of the contiguous part of the memory plane, from
* its beginning to the limit of the MemorySpace size.
* If the MemoryPlane fill the MemorySpace without wrapping, the contiguous
* size will be the same as the total size of the MemoryPlane.
*
* @return unsigned int Contiguous size in words
*/
inline unsigned int getContiguousSize() const {
return std::min(getSize(), getLimit());
}
/**
* @brief Get the absolute offset of the wrapped part of the memory plane.
* Since the wrapped part of the memory plane begins at the beginning of
* the MemorySpace, the returned offset is always the same as the MemorySpace
* offset.
*
* @return unsigned int Wrapped offset in words
*/
inline unsigned int getWrappedOffset() const {
return memSpace->offset;
}
/**
* @brief Get the size of the wrapped part of the memory plane, from
* the beginning of the MemorySpace to the total size of the MemoryPlane,
* including the stride.
* If the MemoryPlane fill the MemorySpace without wrapping, the wrapped
* size will 0.
*
* @return unsigned int Wrapped size in words
*/
inline unsigned int getWrappedSize() const {
return getSize() - getContiguousSize();
}
/**
* @brief Get the absolute offset after the end of the memory plane (if it
* is wrapped, the offset will correspond to the end of the wrapped part).
* The word at the final offset is not included in the MemoryPlane.
*
* @return unsigned int Final offset in words
*/
inline unsigned int getFinalOffset() const {
return (getWrappedSize() > 0)
? getWrappedOffset() + getWrappedSize()
: getContiguousOffset() + getContiguousSize();
}
/**
* @brief Get the absolute offset after the end of the contiguous part
* of the memory plane.
* The word at the upper offset is not included in the MemoryPlane.
*
* @return unsigned int Upper offset in words
*/
inline unsigned int getUpperOffset() const {
return (getContiguousOffset() + getContiguousSize());
}
......@@ -146,10 +247,29 @@ public:
std::shared_ptr<MemorySpace> memSpace;
Clock_T allocated;
/// Relative offset of the MemoryPlane in the MemorySpace (in words)
unsigned int offset;
/// Number of channels, or memory blocks, *in this MemoryPlane*,
/// of \p count lines of size \p length.
/// In the case of concatenation, there can be multiple overlapping MemoryPlane
/// with different size, like NHWC = NHW(C1+C2):
/// - MemoryPlane#1: \p size = C1 and \p stride = C=C1+C2
/// - MemoryPlane#2: \p size = C2 and \p stride = C=C1+C2
/// (with an additionnal relative offset of +C1)
/// By default, \p stride = \p size, \p count = 1 and \p length = 1, meaning
/// there is no NHWC layout and the MemoryPlane can be wrapped **anywhere**.
/// In this case, \p size is the total size of the MemoryPlane (H*W*C, in words).
unsigned int size;
/// Number of channels, or memory blocks *in total*,
/// of \p count lines of size \p length (the C in NHWC).
/// There should be C blocks of H*W size.
unsigned int stride;
/// Size of an elementary, contiguous and non-breakable, memory line
/// (the W in NHWC), in words. A MemoryPlane wrapping cannot occur in
/// the middle of a memory line.
unsigned int length;
/// Number of memory lines of size \p length constituting a memory block
/// (the H in NHWC). The size of a memory block is H*W.
unsigned int count;
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment