Skip to content

Commit

Permalink
Merge pull request microsoft#6 from chenfeiyue-cfy/vsinpu
Browse files Browse the repository at this point in the history
Added pool/matmul/flatten ops
  • Loading branch information
sunshinemyson authored Feb 22, 2024
2 parents d584c4c + c676383 commit d1611cf
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class ConvOpBuilder : public BaseOpBuilder {
}
}
} else {
auto pads = helper.Get("pads", default_vec);
auto pads = helper.Get("pads", std::vector<uint32_t>{0U,0U});
if (group != 1) {
if (is_1d_conv) {
op = graph_ep->GetGraph()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/****************************************************************************
*
* Copyright (c) 2024 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#include "core/providers/vsinpu/builders/impl/base_op_builder.h"
#include "core/providers/common.h"
#include "core/providers/shared/utils/utils.h"

namespace onnxruntime {
namespace vsi {
namespace npu {
class FlattenOpBuilder : public BaseOpBuilder {
bool HandleBuildOp(vsi::npu::GraphEP* graph_ep,
std::vector<std::shared_ptr<tim::vx::Tensor>>& inputs,
std::vector<std::shared_ptr<tim::vx::Tensor>>& outputs,
const Node* node) override {
LOGS_DEFAULT(VERBOSE) << "Creating Flatten Op.";
std::vector<uint32_t> reshape_param;
if (outputs[0]->GetShape().size() == 2)
reshape_param = outputs[0]->GetShape();
else {
auto input_shape = inputs[0]->GetShape();
NodeAttrHelper helper(*node);
int64_t axis = helper.Get("axis", 0);
if (axis < 0) {
axis = HandleNegativeAxis(axis, inputs[0]->GetShape().size()); // handle negative and enforce axis is valid
}
uint32_t first_dim = 1;
for (int64_t i = 0; i < axis; i++) {
first_dim *= inputs[0]->GetShape()[i];
}
uint32_t second_dim = inputs[0]->GetSpec().GetElementNum() / first_dim;
reshape_param.push_back(first_dim);
reshape_param.push_back(second_dim);
}
auto op = graph_ep->GetGraph()->CreateOperation<tim::vx::ops::Reshape>(reshape_param);
(*op).BindInput(inputs[0]).BindOutput(outputs[0]);
graph_ep->GetOps().push_back(std::move(op));
return true;
}
};
} // namespace npu

} // namespace vsi
} // namespace onnxruntime
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/****************************************************************************
*
* Copyright (c) 2024 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
#include "core/providers/vsinpu/builders/impl/base_op_builder.h"

namespace onnxruntime {
namespace vsi {
namespace npu {
class MatMulOpBuilder : public BaseOpBuilder {
bool IsOpSupported(const onnxruntime::GraphViewer& graph_viewer,
const Node* node) const override {
auto output_defs = node->OutputDefs();
if (output_defs[0]->Shape()->dim_size() == 0) {
LOGS_DEFAULT(ERROR) << "Inner product of 1-D tensor is not supported in MatMul op.";
return false;
}
return true;
}
bool HandleBuildOp(vsi::npu::GraphEP* graph_ep,
std::vector<std::shared_ptr<tim::vx::Tensor>>& inputs,
std::vector<std::shared_ptr<tim::vx::Tensor>>& outputs,
const Node* node) override {
LOGS_DEFAULT(VERBOSE) << "Creating Matmul Op.";
auto op = graph_ep->GetGraph()->CreateOperation<tim::vx::ops::Matmul>();
(*op).BindInputs(inputs).BindOutputs(outputs);
graph_ep->GetOps().push_back(std::move(op));
return true;
}
};
} // namespace npu

} // namespace vsi
} // namespace onnxruntime
113 changes: 103 additions & 10 deletions onnxruntime/core/providers/vsinpu/builders/impl/pool_op_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,119 @@
*
*****************************************************************************/
#include "core/providers/vsinpu/builders/impl/base_op_builder.h"
#include "core/providers/shared/utils/utils.h"

namespace onnxruntime {
namespace vsi {
namespace npu {
class GlobalAveragePoolOpBuilder : public BaseOpBuilder {
class BasePoolOpBuilder : public BaseOpBuilder {
public:
BasePoolOpBuilder(tim::vx::PoolType pool_type) : pool_type_(pool_type) {}

protected:
bool IsOpSupported(const onnxruntime::GraphViewer& graph_viewer, const Node* node) const override {
auto shape = vsi::npu::util::GetTensorShape(*node->InputDefs()[0]);
if (shape.NumDimensions() == 5) {
LOGS_DEFAULT(ERROR) << "3DPool is not supported yet.";
return false;
}

NodeAttrHelper helper(*node);
if (helper.HasAttr("dilations")) {
LOGS_DEFAULT(ERROR) << "NonMaxPool with Dilation parameter is not supported.";
return false;
}
return true;
}
bool CreatePoolingOp(vsi::npu::GraphEP* graph_ep,
std::vector<std::shared_ptr<tim::vx::Tensor>>& inputs,
std::vector<std::shared_ptr<tim::vx::Tensor>>& outputs,
const std::array<uint32_t, 2>& kernel_size,
const std::array<uint32_t, 2>& strides,
const std::array<uint32_t, 4>& pads,
bool is_global,
const tim::vx::RoundType ceil_mode) {
const bool is_1d_pool = inputs[0]->GetShape().size() == 3;
std::shared_ptr<tim::vx::Operation> op;

// Create the appropriate pooling operation
if (is_global) {
if (is_1d_pool) {
op = graph_ep->GetGraph()->CreateOperation<tim::vx::ops::Pool1d>(pool_type_, inputs[0]->GetShape()[0], ceil_mode);
} else {
std::array<uint32_t, 2> input_size = {inputs[0]->GetShape()[0], inputs[0]->GetShape()[1]};
op = graph_ep->GetGraph()->CreateOperation<tim::vx::ops::Pool2d>(pool_type_, input_size, ceil_mode);
}

} else {
if (is_1d_pool) {
op = graph_ep->GetGraph()->CreateOperation<tim::vx::ops::Pool1d>(pool_type_, std::array<uint32_t, 2>{pads[2], pads[0]}, kernel_size[1], strides[1], ceil_mode);
} else {
op = graph_ep->GetGraph()->CreateOperation<tim::vx::ops::Pool2d>(pool_type_, pads, kernel_size, strides, ceil_mode);
}
}

op->BindInputs(inputs).BindOutputs(outputs);
graph_ep->GetOps().push_back(op);
return true;
}
tim::vx::PoolType pool_type_;
};

class TraditionalPoolOpBuilder : public BasePoolOpBuilder {
public:
TraditionalPoolOpBuilder() : BasePoolOpBuilder(tim::vx::PoolType::MAX) {}

protected:
bool HandleBuildOp(vsi::npu::GraphEP* graph_ep,
std::vector<std::shared_ptr<tim::vx::Tensor>>& inputs,
std::vector<std::shared_ptr<tim::vx::Tensor>>& outputs,
const Node* node) override {
LOGS_DEFAULT(VERBOSE) << "Creating GlobalAveragePool Op.";
std::array<uint32_t, 2> ksize;
ksize[0] = inputs[0]->GetShape()[0];
ksize[1] = inputs[0]->GetShape()[1];
auto op = graph_ep->GetGraph()->CreateOperation<tim::vx::ops::Pool2d>(
tim::vx::PoolType::AVG, ksize);
(*op).BindInputs(inputs).BindOutputs(outputs);
graph_ep->GetOps().push_back(std::move(op));
return true;
NodeAttrHelper helper(*node);
auto ksize = helper.Get("kernel_shape", std::vector<uint32_t>{1U, 1U});
auto strides = helper.Get("strides", std::vector<uint32_t>{1U, 1U});
auto pads = helper.Get("pads", std::vector<uint32_t>{0U, 0U, 0U, 0U});
tim::vx::RoundType ceil_mode = helper.Get("ceil_mode", 0U) == 0 ? tim::vx::RoundType::FLOOR : tim::vx::RoundType::CEILING;
return CreatePoolingOp(graph_ep, inputs, outputs,
{ksize[1], ksize[0]}, {strides[1], strides[0]}, {pads[1], pads[3], pads[0], pads[2]}, false, ceil_mode);
}
};

class GlobalPoolOpBuilder : public BasePoolOpBuilder {
public:
GlobalPoolOpBuilder() : BasePoolOpBuilder(tim::vx::PoolType::MAX) {}

protected:
bool HandleBuildOp(vsi::npu::GraphEP* graph_ep,
std::vector<std::shared_ptr<tim::vx::Tensor>>& inputs,
std::vector<std::shared_ptr<tim::vx::Tensor>>& outputs,
const Node* node) override {
NodeAttrHelper helper(*node);
tim::vx::RoundType ceil_mode = helper.Get("ceil_mode", 0U) == 0 ? tim::vx::RoundType::FLOOR : tim::vx::RoundType::CEILING;
return CreatePoolingOp(graph_ep, inputs, outputs, {}, {}, {}, true, ceil_mode);
}
};

class GlobalAveragePoolOpBuilder : public GlobalPoolOpBuilder {
public:
GlobalAveragePoolOpBuilder() { pool_type_ = tim::vx::PoolType::AVG; }
};

class GlobalMaxPoolOpBuilder : public GlobalPoolOpBuilder {
public:
GlobalMaxPoolOpBuilder() { pool_type_ = tim::vx::PoolType::MAX; }
};

class AveragePoolOpBuilder : public TraditionalPoolOpBuilder {
public:
AveragePoolOpBuilder() { pool_type_ = tim::vx::PoolType::AVG; }
};

class MaxPoolOpBuilder : public TraditionalPoolOpBuilder {
public:
MaxPoolOpBuilder() { pool_type_ = tim::vx::PoolType::MAX; }
};

} // namespace npu

} // namespace vsi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include "impl/gemm_op_builder.h"
#include "impl/pool_op_builder.h"
#include "impl/qlinearconv_op_builder.h"
#include "impl/flatten_op_builder.h"
#include "impl/matmul_op_builder.h"
namespace onnxruntime {
namespace vsi {
namespace npu {
Expand Down Expand Up @@ -61,7 +63,12 @@ static const std::map<std::string, createIOpBuildItemFunc> reg = {
REGISTER_OP_BUILDER("HardSigmoid", HardSigmoidOpBuilder),
REGISTER_OP_BUILDER("HardSwish", HardSwishOpBuilder),
REGISTER_OP_BUILDER("GlobalAveragePool", GlobalAveragePoolOpBuilder),
REGISTER_OP_BUILDER("QLinearConv", QLinearConvOpBuilder)
REGISTER_OP_BUILDER("QLinearConv", QLinearConvOpBuilder),
REGISTER_OP_BUILDER("Flatten", FlattenOpBuilder),
REGISTER_OP_BUILDER("MatMul", MatMulOpBuilder),
REGISTER_OP_BUILDER("GlobalMaxPool", GlobalMaxPoolOpBuilder),
REGISTER_OP_BUILDER("AveragePool", AveragePoolOpBuilder),
REGISTER_OP_BUILDER("MaxPool", MaxPoolOpBuilder),

#undef REGISTER_OP_BUILDER
};
Expand Down

0 comments on commit d1611cf

Please sign in to comment.