SMAUG
Simulating Machine Learning Applications on gem5-Aladdin
tensor_utils.h
Go to the documentation of this file.
1 
6 #ifndef _CORE_TENSOR_UTILS_H_
7 #define _CORE_TENSOR_UTILS_H_
8 
9 #include <cstring>
10 #include <iostream>
11 #include <vector>
12 
13 #include "smaug/core/tensor.h"
14 
15 namespace smaug {
16 
17 class Workspace;
18 class Operator;
19 
20 std::ostream& operator<<(std::ostream& os, const TensorIndexIterator& iter);
21 std::ostream& operator<<(std::ostream& os, const TensorShape& shape);
22 std::ostream& operator<<(std::ostream& os, const Tensor& tensor);
23 
24 template <typename DType>
25 void printTensorElement(std::ostream& os, const DType* data, int index) {
26  os << data[index];
27 }
28 
29 template <>
30 void printTensorElement<float16>(std::ostream& os,
31  const float16* data,
32  int index);
33 
37 template <typename DType>
38 void writeTensorToOstream(std::ostream& os, const Tensor& tensor) {
39  const TensorShape& shape = tensor.getShape();
40  if (shape.ndims() == 0) {
41  os << " [ ]\n";
42  return;
43  }
44  int ndims = shape.ndims();
45  int newlineAfterElems = shape[ndims - 1];
46  int newGroupAfterElems =
47  (shape.ndims() >= 2 ? shape[ndims - 1] * shape[ndims - 2]
48  : shape[ndims - 1]);
49  int counter = 0;
50  const DType* data = tensor.template data<DType>();
51  os << tensor.getName() << ", shape = " << shape << "\n";
52  for (auto idx = tensor.startIndex(); !idx.end(); ++idx) {
53  // Print the current index after going through all of the last two
54  // dimensions.
55  if (counter == 0)
56  os << idx << "\n[ ";
57  printTensorElement<DType>(os, data, idx);
58  os << " ";
59  ++counter;
60  if (counter % newGroupAfterElems == 0) {
61  counter = 0;
62  os << " ]\n";
63  } else if (counter % newlineAfterElems == 0) {
64  os << "\n ";
65  }
66  }
67 }
68 
69 namespace internal {
70 
71 template <typename DType>
72 void copyTensorRegion(Tensor* dest,
73  Tensor* src,
74  const std::vector<int>& destOrigin,
75  const std::vector<int>& srcOrigin,
76  const std::vector<int>& regionSize) {
77  const TensorShape& srcShape = src->getShape();
78  const TensorShape& destShape = dest->getShape();
79  TensorShape regionShape(
80  regionSize, srcShape.getLayout(), srcShape.getAlignment());
81  const int ndims = srcShape.ndims();
82  auto destIt = TensorRegionIndexIterator(destShape, destOrigin, regionSize);
83  auto srcIt = TensorRegionIndexIterator(srcShape, srcOrigin, regionSize);
84 
85  // We know where to copy data from and how much data we should copy (the
86  // data region), now starting from the last dimension, we figure out how
87  // much contiguous data there exists such that we can apply more efficient
88  // data copy mechanisms (memcpy).
89  std::vector<int> contiguousRegion(ndims, 1);
90  int contiguousSize = 1;
91  for (int i = ndims - 1; i >= 0; i--) {
92  contiguousSize *= regionShape.getStorageDim(i);
93  contiguousRegion[i] = regionShape[i];
94  // If we find a region dimension smaller than that of either src or
95  // dest tensor, then the next region dimension must not be contiguous.
96  if (regionShape[i] < srcShape[i] || regionShape[i] < destShape[i])
97  break;
98  }
99 
100  // Copy the data region from the src tensor to the dest tensor.
101  DType* destPtr = dest->template data<DType>();
102  DType* srcPtr = src->template data<DType>();
103  while (!srcIt.end() && !destIt.end()) {
104 #ifdef PEDANTIC
105  destPtr[destIt] = srcPtr[srcIt];
106  ++destIt;
107  ++srcIt;
108 #else
109  memcpy(&destPtr[destIt],
110  &srcPtr[srcIt],
111  contiguousSize * sizeof(DType));
112  destIt += contiguousRegion;
113  srcIt += contiguousRegion;
114 #endif
115  }
116 }
117 
118 template <typename DType>
119 void copyRawTensorData(Tensor* dest,
120  Tensor* src,
121  int destOffset,
122  int srcOffset,
123  int copySize) {
124  DType* destPtr = dest->template data<DType>();
125  DType* srcPtr = src->template data<DType>();
126  std::memcpy(
127  &destPtr[destOffset], &srcPtr[srcOffset], copySize * sizeof(DType));
128 }
129 
130 template <typename DType>
131 void copyTensorData(Tensor* dest,
132  Tensor* src,
133  std::vector<int> destOrigin,
134  std::vector<int> srcOrigin,
135  int copySize) {
136  TensorIndexIterator destIdx = dest->startIndex();
137  TensorIndexIterator srcIdx = src->startIndex();
138  destIdx += destOrigin;
139  srcIdx += srcOrigin;
140  DType* destPtr = dest->template data<DType>();
141  DType* srcPtr = src->template data<DType>();
142  for (; !srcIdx.end(); ++srcIdx, ++destIdx)
143  destPtr[destIdx] = srcPtr[srcIdx];
144 }
145 
146 } // namespace internal
147 
148 // Copy a region of data from one tensor to another.
149 //
168 void copyTensorRegion(Tensor* dest,
169  Tensor* src,
170  std::vector<int> destOrigin,
171  std::vector<int> srcOrigin,
172  std::vector<int> regionSize);
173 
178 void copyTensorData(Tensor* dest,
179  Tensor* src,
180  std::vector<int> destOffset,
181  std::vector<int> srcOffset,
182  int copySize);
183 
196 void copyRawTensorData(
197  Tensor* dest, Tensor* src, int destOffset, int srcOffset, int copySize);
198 
211 TiledTensor generateTiledTensorPerBatchNC(Tensor* tensor,
212  const TensorShape& tileShape,
213  Operator* op,
214  bool copyData = true);
215 
234  Tensor* tensor,
235  const TensorShape& tileShape,
236  Operator* op,
237  int fieldRows,
238  int fieldCols,
239  int rowStride,
240  int colStride,
241  PaddingType paddingType,
242  bool copyData = false);
243 
255 TiledTensor generateTiledTensor(Tensor* tensor,
256  const TensorShape& tileShape,
257  Operator* op,
258  bool copyData = false);
259 
264 void flattenTiledTensor(TiledTensor& tiledTensor, Tensor* destTensor);
265 
269 Tensor* concatTensors(std::vector<Tensor*> inputTensors,
270  int concatDim,
271  Workspace* workspace);
272 
273 } // namespace smaug
274 
275 #endif
smaug::Tensor
Tensor represents a single multi-dimensional array of data.
Definition: tensor.h:344
smaug::Tensor::startIndex
TensorIndexIterator startIndex() const
Returns an iterator starting at the beginning of the Tensor.
Definition: tensor.h:387
smaug::concatTensors
Tensor * concatTensors(std::vector< Tensor * > inputTensors, int concatDim, Workspace *workspace)
Concatenates Tensors on the specified dimension into one single tensor.
Definition: tensor_utils.cpp:357
smaug::copyTensorRegion
void copyTensorRegion(Tensor *dest, Tensor *src, std::vector< int > destOrigin, std::vector< int > srcOrigin, std::vector< int > regionSize)
Copies a region of a source Tensor to a corresponding region in a destination Tensor.
Definition: tensor_utils.cpp:65
smaug::copyTensorData
void copyTensorData(Tensor *dest, Tensor *src, std::vector< int > destOrigin, std::vector< int > srcOrigin, int copySize)
Similar to copyTensorRegion, but the region is a contiguous block of memory.
Definition: tensor_utils.cpp:102
smaug::writeTensorToOstream
void writeTensorToOstream(std::ostream &os, const Tensor &tensor)
Pretty-print a Tensor's name, shape, and contents to the provided ostream.
Definition: tensor_utils.h:38
smaug::copyRawTensorData
void copyRawTensorData(Tensor *dest, Tensor *src, int destOffset, int srcOffset, int copySize)
Directly copies a linear region of memory from dest to src, without taking dimensions/padding into ac...
Definition: tensor_utils.cpp:138
smaug::generateTiledTensorPerBatchNC
TiledTensor generateTiledTensorPerBatchNC(Tensor *tensor, const TensorShape &tileShape, Operator *op, bool copyData)
Tile the provided NC Tensor per batch.
Definition: tensor_utils.cpp:199
smaug::TensorShape
TensorShape describes the shape of a Tensor.
Definition: tensor.h:35
smaug::generateTiledTensorWithStrideAndPadding
TiledTensor generateTiledTensorWithStrideAndPadding(Tensor *tensor, const TensorShape &tileShape, Operator *op, int fieldRows, int fieldCols, int rowStride, int colStride, PaddingType paddingType, bool copyData)
Generates a TiledTensor from a source Tensor with the specified tile shape.
Definition: tensor_utils.cpp:233
smaug
The smaug namespace is the parent namespace of all C++ code in SMAUG.
Definition: backend.cpp:38
smaug::generateTiledTensor
TiledTensor generateTiledTensor(Tensor *tensor, const TensorShape &tileShape, Operator *op, bool copyData)
Generates a TiledTensor from a source Tensor.
Definition: tensor_utils.cpp:335
smaug::flattenTiledTensor
void flattenTiledTensor(TiledTensor &tiledTensor, Tensor *destTensor)
Copies the data from each tile in a TiledTensor into a destination Tensor as a contiguous block of me...
Definition: tensor_utils.cpp:343