Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a padding operator. #95

Merged
merged 11 commits into from
Jul 17, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
tags
build/
experiments/
smaug/operators/padding_op_test.h
*.pyc
__pycache__
*.swp
*.swo
10 changes: 5 additions & 5 deletions smaug/core/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ DEF_CREATE_OP(PaddingOp, SmvBackend)

// for simple tracing.
namespace ref {
const unsigned kConvolutionHw = 0x0001; // 0x0001;
const unsigned kInnerProductHw = 0x0001; // 0x0002;
const unsigned kEltwiseOpHw = 0x0001; // 0x0003;
const unsigned kBatchNormHw = 0x0001; // 0x0004;
const unsigned kPoolingHw = 0x0001; // 0x0005;
const unsigned kConvolutionHw = 0x0001;
const unsigned kInnerProductHw = 0x0002;
const unsigned kEltwiseOpHw = 0x0003;
const unsigned kBatchNormHw = 0x0004;
const unsigned kPoolingHw = 0x0005;
} // namespace ref

namespace smv {
Expand Down
4 changes: 2 additions & 2 deletions smaug/core/network_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,9 @@ static void createAndAddOperator(const NodeProto& node,
} else if (type == OpType::Tanh) {
auto op = Backend::createTanhOp(name, workspace);
network->addOperator(op);
} else if (type == OpType::Padding) { // how to set this
} else if (type == OpType::Padding) {
auto op = Backend::createPaddingOp(name, workspace);
op->setPadder(node.params().padding_params().padding_size());
op->setPaddingSize(node.params().padding_params().padding_size());
network->addOperator(op);
} else if (type == OpType::HardTanh) {
auto op = Backend::createHardTanhOp(name, workspace);
Expand Down
2 changes: 1 addition & 1 deletion smaug/core/node.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ message PoolParams {
}

message PaddingParams {
int32 padding_size = 1;
repeated int32 padding_size = 1;
}

message ConcatParams {
Expand Down
122 changes: 61 additions & 61 deletions smaug/core/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,80 +3,80 @@ syntax = "proto3";
package smaug;

enum DataType {
UnknownDataType = 0;
Int32 = 1;
Int64 = 2;
Float16 = 3;
Float32 = 4;
Float64 = 5;
Bool = 6;
UnknownDataType = 0;
Int32 = 1;
Int64 = 2;
Float16 = 3;
Float32 = 4;
Float64 = 5;
Bool = 6;
}

enum DataLayout {
option allow_alias = true;
UnknownLayout = 0;
NCHW = 1;
NHWC = 2;
NC = 4;
CN = 8;
NCT = 16;
NTC = 32;
N = 64;
X = 127; // Elementwise
EndDataLayout = 64;
option allow_alias = true;
UnknownLayout = 0;
NCHW = 1;
NHWC = 2;
NC = 4;
CN = 8;
NCT = 16;
NTC = 32;
N = 64;
X = 127; // Elementwise
EndDataLayout = 64;
}

enum DataStorageFormat {
UnknownStorageFormat = 0;
Uncompressed = 1;
CSR = 2;
PackedCSR = 3;
UncompressedHalfPrecision = 4;
UnknownStorageFormat = 0;
Uncompressed = 1;
CSR = 2;
PackedCSR = 3;
UncompressedHalfPrecision = 4;
}

enum OpType {
UnknownOp = 0;
Convolution3d = 1;
ConvolutionDepthwise = 2;
MaxPooling = 3;
AveragePooling = 4;
InnerProduct = 5;
BatchNorm = 6;
Data = 7;
ReLU = 8;
LReLU = 9;
ELU = 10;
SELU = 11;
Tanh = 12;
HardTanh = 13;
Sigmoid = 14;
Softmax = 15;
EltwiseAdd = 16;
Reorder = 17;
EltwiseMul = 18;
Concat = 19;
Split = 20;
Reshape = 21;
Repeat = 22;
Less = 23;
LessEqual = 24;
Greater = 25;
GreaterEqual = 26;
Switch = 27;
Merge = 28;
Padding = 29;
UnknownOp = 0;
Convolution3d = 1;
ConvolutionDepthwise = 2;
MaxPooling = 3;
AveragePooling = 4;
InnerProduct = 5;
BatchNorm = 6;
Data = 7;
ReLU = 8;
LReLU = 9;
ELU = 10;
SELU = 11;
Tanh = 12;
HardTanh = 13;
Sigmoid = 14;
Softmax = 15;
EltwiseAdd = 16;
Reorder = 17;
EltwiseMul = 18;
Concat = 19;
Split = 20;
Reshape = 21;
Repeat = 22;
Less = 23;
LessEqual = 24;
Greater = 25;
GreaterEqual = 26;
Switch = 27;
Merge = 28;
Padding = 29;
}

enum PaddingType {
UnknownPadding = 0;
SamePadding = 1;
ValidPadding = 2;
UnknownPadding = 0;
SamePadding = 1;
ValidPadding = 2;
}

enum HostMemoryAccessPolicy {
UnknownMemoryPolicy = 0;
AllDma = 1;
AllAcp = 2;
AllCache = 3;
AllAcpWithDmaForWeights = 4;
UnknownMemoryPolicy = 0;
AllDma = 1;
AllAcp = 2;
AllCache = 3;
AllAcpWithDmaForWeights = 4;
}
107 changes: 45 additions & 62 deletions smaug/operators/padding_op.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
#include "smaug/core/backend.h"
#include "smaug/core/operator.h"
#include "smaug/core/tensor.h"
// #include "smaug/core/tensor_utils.h"
#include "smaug/core/workspace.h"
#include <google/protobuf/repeated_field.h>
using namespace google::protobuf;

namespace smaug {

/** \ingroup Operators
* \brief Pad a given tensor in different dimension.
* \brief Pad a given tensor in any number of dimensions with arbitrary size.
*
* This has a software-based implementation.
*
Expand All @@ -19,95 +20,77 @@ namespace smaug {
template <typename Backend>
class PaddingOp : public Operator {
public:
PaddingOp(const std::string& name,
Workspace* workspace)
: Operator(name, OpType::Repeat, workspace){
PaddingOp(const std::string& name, Workspace* workspace)
: Operator(name, OpType::Padding, workspace) {
inputs.resize(kNumInputs, nullptr);
outputs.resize(kNumOutputs, nullptr);
}

PaddingOp(const std::string& name,
Workspace* workspace,
int val)
: Operator(name, OpType::Repeat, workspace), padder(val){
inputs.resize(kNumInputs, nullptr);
outputs.resize(kNumOutputs, nullptr);
/**
* Set the paddingSize of the Tensor along each dimension.
* The paddingSize is orgainized as <dim1_forward, dim1_backward, ...
* ,dimk_backward>
*/
void setPaddingSize(RepeatedField<google::protobuf::int32> const& val) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be const RepeatedField&, not RepeatedField const&.

Also, what does "forward" and "backward" mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll update this.

paddingSize.assign(val.begin(), val.end());
}

/** Set the number of padders of the Tensor along each dimension. */
void setPadder(const int& val) {
padder = val;
// set output size?
}
void setPaddingSize(std::vector<int> const& val) { paddingSize = val; }

int getPadder() { return padder; }
std::vector<int> getPaddingSize() const { return paddingSize; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return const std::vector& to avoid making a copy of paddingSize.


void run() override {
Tensor* input = getInput(0);
Tensor* output = getOutput(0);
int ndims = input->ndims();
std::vector<int> inputDims = input->getShape().dims();
std::vector<int> outputDims = output->getShape().dims();
int total_dim = 1;
for (int i: outputDims){
total_dim *= i;
}
std::vector<float> vf(total_dim, 0);
output->fillData(vf.data(), vf.size());
/*
copyTensorRegion(Tensor* dest,
Tensor* src,
const std::vector<int>& destOrigin,
const std::vector<int>& srcOrigin,
const std::vector<int>& regionSize
*/
std::vector<int> destOrigin;
if (input->getShape().getLayout() == DataLayout::NCHW){
destOrigin = std::vector<int>({0, 0, padder, padder});
}
else if(input->getShape().getLayout() == DataLayout::NHWC){
destOrigin = std::vector<int>({0, padder, padder, 0});
}
else{
assert(false && "Invalid padding data type!");
}
std::vector<int> srcOrigin = std::vector<int>({0, 0, 0, 0});
std::vector<int> regionSize = inputDims;
copyTensorRegion(output, input, destOrigin, srcOrigin, regionSize);
Tensor* input = getInput(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the enums defined below (kInput and kOutput) to access all the input/output tensors, here and everywhere else in this file.

Tensor* output = getOutput(0);
int ndims = input->ndims();
const std::vector<int> inputDims = input->getShape().dims();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both inputDims and outputDims should be const-ref.

const std::vector<int> outputDims = output->getShape().dims();
int total_dim = 1;
for (int i : outputDims) {
total_dim *= i;
}
std::vector<float> vf(total_dim, 0);
output->fillData(vf.data(), vf.size());
std::vector<int> destOrigin, paddingBegin, srcOrigin;
for (int i = 0; i < ndims; i++) {
paddingBegin.push_back(paddingSize[2 * i]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use paddingSize.at(2*i) instead; this will throw an exception if you go out of bounds, whereas paddingSize[] will attempt to add an element at that position.

srcOrigin.push_back(0);
}
destOrigin = std::vector<int>(paddingBegin);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to declare destOrigin earlier and then re-initialize it here - that causes the vector to be constructed twice. Just declare it here directly: std::vector<int> destOrigin = ....

std::vector<int> regionSize = inputDims;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here - no need to make a copy of inputDims, just use it directly. I think you're trying to make it more clear what each vector is representing in the copyTensorRegion call but there's no need since the API documents it very clearly already.

copyTensorRegion(output, input, destOrigin, srcOrigin, regionSize);
}

// Optional override for testing purposes.
void createAllTensors() override {
Tensor* input = getInput(0);
int ndims = input->ndims();
std::vector<int> dims = input->getShape().dims();
if (input->getShape().getLayout() == DataLayout::NCHW){
dims[2] += 2*padder;
dims[3] += 2*padder;
}
else if (input->getShape().getLayout() == DataLayout::NHWC){
dims[1] += 2*padder;
dims[2] += 2*padder;
for (int i = 0; i < ndims; i++) {
dims[i] += (paddingSize[2 * i] + paddingSize[2 * i + 1]);
}
TensorShape shape(
dims, input->getShape().getLayout(), Backend::Alignment);
Tensor* output = new Tensor(name, shape);
workspace->addTensor(output);
outputs.at(0) = output;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here - use enums instead of hardcoded constants.

}
}

// Optional but recommended function to verify operator parameters.
bool validate() override {
if (padder < 0){
return false;
}
Tensor* input = getInput(0);
int ndims = input->ndims();
if (paddingSize.size() != 2 * ndims) {
return false;
}
return Operator::validate();
}

enum { kInputs, kNumInputs };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: kInput instead of kInputs (you only have one), and likewise for outputs.

enum { kOutputs, kNumOutputs };

private:
int padder = 0;
private:
std::vector<int> paddingSize = {};
};

} // namespace smaug
Expand Down
Loading