SMAUG
Simulating Machine Learning Applications on gem5-Aladdin
smv_unary_op_common.cpp
1 #include "smaug/core/backend.h"
4 #include "smaug/operators/smv/smv_unary_op_common.h"
5 #include "smaug/operators/smv/smv_relu_op.h"
6 #include "smaug/operators/smv/smv_elu_op.h"
7 #include "smaug/operators/smv/smv_tanh_op.h"
8 #include "smaug/operators/smv/smv_sigmoid_op.h"
9 #include "smaug/operators/smv/smv_kernels.h"
10 #include "smaug/utility/debug_stream.h"
11 
12 namespace smaug {
13 namespace smv {
14 namespace unary {
15 
16 std::pair<activation_type, activation_param_t> getActivationParams(
17  UnaryOp<SmvBackend>* op) {
18  activation_type function;
19  activation_param_t params;
20  OpType opType = op->getOpType();
21  if (opType == OpType::ReLU) {
22  auto reluOp = dynamic_cast<SmvReluOp*>(op);
23  params.slope = reluOp->getSlope();
24  if (params.slope > 0)
25  function = activation_type::LRELU;
26  else
27  function = activation_type::RELU;
28  } else if (opType == OpType::ELU) {
29  function = activation_type::ELU;
30  auto eluOp = dynamic_cast<SmvEluOp*>(op);
31  params.alpha = eluOp->getAlpha();
32  } else if (opType == OpType::SELU) {
33  function = activation_type::SELU;
34  auto seluOp = dynamic_cast<SmvSeluOp*>(op);
35  params.alpha = seluOp->getAlpha();
36  params.lambda = seluOp->getLambda();
37  } else if (opType == OpType::Tanh) {
38  function = activation_type::TANH;
39  } else if (opType == OpType::HardTanh) {
40  function = activation_type::HARD_TANH;
41  auto hardTanhOp = dynamic_cast<SmvHardTanhOp*>(op);
42  params.min = hardTanhOp->getMin();
43  params.max = hardTanhOp->getMax();
44  } else if (opType == OpType::Sigmoid) {
45  function = activation_type::SIGMOID;
46  } else if (opType == OpType::Softmax) {
47  assert(false && "Softmax should call its own run() implementation!");
48  }
49  return { function, params };
50 }
51 
52 // The tile dispatcher for activation functions.
53 void runX(UnaryOp<SmvBackend>* op, TiledTensor& inputs, TiledTensor& outputs) {
54  assert(inputs.size() == outputs.size());
55  auto actParams = getActivationParams(op);
57  smv::kEltwiseOpHw, "host_inputs", op->getInputsMemType());
59  smv::kEltwiseOpHw, "host_results", op->getOutputsMemType());
60  for (int i = 0; i < inputs.size(); i++) {
61  dout(1) << "Input: " << i << ", output: " << i << "\n";
62  Tensor* inputTile = inputs.getTileWithData(i);
63  Tensor* outputTile = outputs[i];
64  const TensorShape& inputShape = inputTile->getShape();
65  const TensorShape& outputShape = outputTile->getShape();
66  mapArrayToAccel(smv::kEltwiseOpHw, "host_inputs",
67  inputTile->data<float16>(),
68  inputShape.storageSize() * sizeof(float16));
69  mapArrayToAccel(smv::kEltwiseOpHw, "host_results",
70  outputTile->data<float16>(),
71  outputShape.storageSize() * sizeof(float16));
72 
74  inputTile->data<float16>(), outputTile->data<float16>(),
75  smv::spad0, smv::spad1, inputShape.storageSize(),
76  actParams.first, actParams.second);
77  }
78 }
79 
80 std::array<TiledTensor, 2> doTiling(UnaryOp<SmvBackend>* op, bool copyData) {
81  auto inputs = op->getInput(UnaryOp<SmvBackend>::Inputs);
82  auto outputs = op->getOutput(UnaryOp<SmvBackend>::Outputs);
83  // The tiling for unary operators can be greatly simplified in comparison to
84  // other operators. The tile shape is determined as [1, spadSize].
85  int maxTileSize =
86  std::min(SmvBackend::SpadSize() / inputs->getDataTypeSize(),
87  inputs->getShape().storageSize());
88  TensorShape tileShape(
89  { 1, maxTileSize }, DataLayout::NC, SmvBackend::Alignment);
91  inputs, tileShape, op, copyData);
93  outputs, tileShape, op, copyData);
94  return { tiledInputs, tiledOutputs };
95 }
96 
97 void run(UnaryOp<SmvBackend>* op, std::array<TiledTensor, 2>& tiledTensors) {
98  auto inputs = op->getInput(UnaryOp<SmvBackend>::Inputs);
99  auto outputs = op->getOutput(UnaryOp<SmvBackend>::Outputs);
100 
101  {
102  auto stats = gem5::ScopedStats(
103  stats::kTensorPrepStart, stats::kTensorPrepEnd);
104  tiledTensors[0].copyDataToAllTiles();
105  }
106 
107  runX(op, tiledTensors[0], tiledTensors[1]);
108 
109  {
110  auto stats = gem5::ScopedStats(
111  stats::kTensorFinalStart, stats::kTensorFinalEnd);
112  flattenTiledTensor(tiledTensors[1], outputs);
113  }
114 }
115 
116 } // namespace unary
117 } // namespace smv
118 } // namespace smaug
119 
smaug::Tensor
Tensor represents a single multi-dimensional array of data.
Definition: tensor.h:344
smaug::Tensor::data
const T * data() const
Returns a const pointer to the Tensor data.
Definition: tensor.h:521
activation_type
enum _activation_type activation_type
The activation function to apply to an operator's output in hardware.
smaug::dout
const DebugStream & dout(int debugLevel)
Returns a DebugStream instance for the given debug level.
Definition: debug_stream.cpp:16
smaug::TiledTensor::getTileWithData
Tensor * getTileWithData(int index)
Returns a Tensor at the specified tile position, with data copied from the original tensor.
Definition: tensor.cpp:65
smaug::SmvReluOp
Rectified linear-unit operator on SMV.
Definition: smv_relu_op.h:12
smaug::TiledTensor
A multidimensional container of Tensors.
Definition: tensor.h:552
tensor_utils.h
Utility functions for copying/printing/tiling tensors.
smaug::setArrayMemTypeIfSimulating
void setArrayMemTypeIfSimulating(unsigned reqCode, const char *arrayName, MemoryType memType)
Sets what memory access mechanism the accelerator will use when accessing this array.
Definition: common.cpp:21
smaug::smv::unary::runX
void runX(UnaryOp< SmvBackend > *op, TiledTensor &inputs, TiledTensor &outputs)
A generic tile dispatcher for unary operators.
Definition: smv_unary_op_common.cpp:53
_activation_param_t
Parameters to the activation function hardware.
Definition: common.h:194
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::SmvEluOp
Elementwise exponential linear unit on SMV.
Definition: smv_elu_op.h:12
smv_activation_fun_nc_vec_fxp
void smv_activation_fun_nc_vec_fxp(float16 *host_inputs, float16 *host_results, float *inputs, float *results, int inputs_size, activation_type function, activation_param_t params)
Definition: activation_functions_simd.c:13
smaug::smv::unary::getActivationParams
std::pair< activation_type, activation_param_t > getActivationParams(UnaryOp< SmvBackend > *op)
Extract activation function parameters from the Operator and stores them in the C-style structs for p...
Definition: smv_unary_op_common.cpp:16
smaug
The smaug namespace is the parent namespace of all C++ code in SMAUG.
Definition: backend.cpp:38
smaug::SmvSeluOp
Elementwise scaled exponential linear unit on SMV.
Definition: smv_elu_op.h:23
common.h
Utilities for writing and invoking Aladdin kernels from Operators.
smaug::SmvHardTanhOp
Hard tanh operator on SMV.
Definition: smv_tanh_op.h:23
smaug::mapArrayToAccel
void mapArrayToAccel(unsigned reqCode, const char *arrayName, void *baseAddr, size_t size)
Maps an array of data to the accelerator.
Definition: common.cpp:12
smaug::UnaryOp
Base class for all operators with one input.
Definition: unary_op.h:20
smaug::invokeKernel
void invokeKernel(int accelIdx, unsigned reqCode, const Kernel &kernel, Args &&... args)
The generic blocking interface for all accelerator kernel functions.
Definition: common.h:72
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