Skip to content

Commit

Permalink
[luci] infer dynamic shape for pad
Browse files Browse the repository at this point in the history
This infers dynamic shape for pad.

DCO-1.0-Signed-off-by: JuYoung Lee <[email protected]>
  • Loading branch information
icodo98 committed Aug 21, 2024
1 parent dec3d68 commit c7a4dca
Show file tree
Hide file tree
Showing 15 changed files with 308 additions and 123 deletions.
7 changes: 1 addition & 6 deletions compiler/luci/export/include/luci/CircleExporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,9 @@ class CircleExporter
virtual ~Contract() = default;

public: // Client -> Exporter
// Input Graph (to be exported)
// Exporter expects a loco graph that consists of Circle nodes
virtual loco::Graph *graph(void) const = 0;

// Input Module (to be exported)
// Exporter expects a luci module that consists of loco graphs
// TODO make this pure virtual
virtual luci::Module *module(void) const;
virtual luci::Module *module(void) const = 0;

public: // Exporter -> Client
// Exporter calls store for export data
Expand Down
1 change: 0 additions & 1 deletion compiler/luci/export/include/luci/CircleFileExpContract.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ struct CircleFileExpContract : public luci::CircleExporter::Contract
virtual ~CircleFileExpContract() = default;

public:
loco::Graph *graph(void) const final { return nullptr; }
luci::Module *module(void) const final { return _module; }

public:
Expand Down
16 changes: 3 additions & 13 deletions compiler/luci/export/src/CircleExporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@
namespace luci
{

// TODO remove this
Module *CircleExporter::Contract::module(void) const { return nullptr; }

CircleExporter::CircleExporter()
{
// NOTHING TO DO
Expand All @@ -48,17 +45,10 @@ bool CircleExporter::invoke(Contract *contract) const
return contract->store(ptr, size);
}

auto graph = contract->graph();
if (graph == nullptr)
return false;

CircleExporterImpl impl(graph);

const char *ptr = impl.getBufferPointer();
const size_t size = impl.getBufferSize();
// NOTE some unit tests calls with nullptr module, cannot add assert here
// TODO fix those unit tests and add assert(false)

// we just send one time
return contract->store(ptr, size);
return false;
}

} // namespace luci
19 changes: 11 additions & 8 deletions compiler/luci/export/src/CircleExporter.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ class SampleGraphContract : public luci::CircleExporter::Contract
SampleGraphContract() : luci::CircleExporter::Contract(), _buffer(new std::vector<char>)
{
// create needed entities
_g = loco::make_graph();
auto graph_input = _g->inputs()->create();
auto graph_output = _g->outputs()->create();
input_node = _g->nodes()->create<luci::CircleInput>();
output_node = _g->nodes()->create<luci::CircleOutput>();
relu_node = _g->nodes()->create<luci::CircleRelu>();
auto g = loco::make_graph();
auto graph_input = g->inputs()->create();
auto graph_output = g->outputs()->create();
input_node = g->nodes()->create<luci::CircleInput>();
output_node = g->nodes()->create<luci::CircleOutput>();
relu_node = g->nodes()->create<luci::CircleRelu>();

// link nodes and link them to graph
relu_node->features(input_node);
Expand All @@ -57,9 +57,12 @@ class SampleGraphContract : public luci::CircleExporter::Contract

graph_output->shape({1, 2, 3, 4});
graph_output->dtype(loco::DataType::FLOAT32);

_m = std::unique_ptr<luci::Module>{new luci::Module};
_m->add(std::move(g));
}

loco::Graph *graph(void) const override { return _g.get(); }
luci::Module *module(void) const override { return _m.get(); }

public:
bool store(const char *ptr, const size_t size) const override
Expand All @@ -77,7 +80,7 @@ class SampleGraphContract : public luci::CircleExporter::Contract
luci::CircleRelu *relu_node;

private:
std::unique_ptr<loco::Graph> _g;
std::unique_ptr<luci::Module> _m;
std::unique_ptr<std::vector<char>> _buffer;
};

Expand Down
58 changes: 1 addition & 57 deletions compiler/luci/export/src/CircleExporterImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ namespace luci
using namespace circle;
using namespace flatbuffers;

CircleExporterImpl::CircleExporterImpl(loco::Graph *graph) { exportGraph(graph); }
CircleExporterImpl::CircleExporterImpl(Module *module) { exportModule(module); }

::flatbuffers::Offset<::circle::SubGraph>
Expand All @@ -148,61 +147,6 @@ CircleExporterImpl::exportSubgraph(SerializedGraphData &gd)
return subgraph;
}

void CircleExporterImpl::exportGraph(loco::Graph *graph)
{
// do graph optimization
optimize(graph);

_builder.Clear();

SerializedModelData md;
SerializedGraphData gd;

// This version is taken from comment in fbs
constexpr uint32_t version = 0;

// set Subgraph name
gd._name = graph->name();

// TODO set this value properly
gd._data_format = circle::DataFormat::DataFormat_CHANNELS_LAST;

// prepare model data
prepareModelData(_builder, md);

// parse graph into SerializedModelData structure
exportOpDefinedTensors(graph, _builder, md, gd);

// NOTE Invoke these register functions only after each node is annotated with its tensor_index
registerGraphInputTensors(graph, gd);
registerGraphOutputTensors(graph, gd);

exportNodes(graph, _builder, md, gd);

// encode operator codes
auto operator_codes = encodeOperatorCodes(_builder, md._operator_codes);

// Subgraphs
Offset<SubGraph> subgraph = exportSubgraph(gd);
auto subgraphs = _builder.CreateVector(std::vector<Offset<SubGraph>>{subgraph});

// Description
std::string description_str = "nnpackage";
auto description = _builder.CreateString(description_str);

// Metadata
auto metadata_vec = createCircleMetadataVector(_builder, md);
auto metadata = _builder.CreateVector(std::vector<Offset<Metadata>>(metadata_vec));

// create array of buffers
auto buffers = _builder.CreateVector(md._buffers);

// Model
auto model_offset = CreateModel(_builder, version, operator_codes, subgraphs, description,
buffers, 0 /* metadata_buffer */, metadata);
FinishModelBuffer(_builder, model_offset);
}

void CircleExporterImpl::exportModule(Module *module)
{
assert(module->size() > 0);
Expand Down Expand Up @@ -248,7 +192,7 @@ void CircleExporterImpl::exportModule(Module *module)
auto operator_codes = encodeOperatorCodes(_builder, md._operator_codes);

// Description
std::string description_str = "nnpackage";
std::string description_str = "ONE-luci/export";
auto description = _builder.CreateString(description_str);

// Metadata
Expand Down
7 changes: 0 additions & 7 deletions compiler/luci/export/src/CircleExporterImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class CircleExporterImpl
CircleExporterImpl() = delete;
~CircleExporterImpl() = default;

explicit CircleExporterImpl(loco::Graph *graph);
explicit CircleExporterImpl(Module *module);

/**
Expand All @@ -59,12 +58,6 @@ class CircleExporterImpl
*/
flatbuffers::Offset<circle::SubGraph> exportSubgraph(SerializedGraphData &gd);

/**
* @brief root function that writes graph into internal buffer
* @param graph
*/
void exportGraph(loco::Graph *graph);

/**
* @brief root function that writes Module into internal buffer
* @param module
Expand Down
39 changes: 23 additions & 16 deletions compiler/luci/service/src/CircleShapeInferenceRule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,27 +237,33 @@ loco::NodeShape use_paddings(const CIRCLENODE *node, const luci::CircleConst *pa
{
int32_t idx = ni * 2;
int value = input_shape.dim(ni).value();
if (paddings->dtype() == S32)
if (!input_shape.dim(ni).known())
{
value += paddings->at<S32>(idx + 0); // left
value += paddings->at<S32>(idx + 1); // right
output_shape.dim(ni).unset();
}
else
{
auto pl = paddings->at<S64>(idx + 0);
auto pr = paddings->at<S64>(idx + 1);
auto max = static_cast<int64_t>(std::numeric_limits<int32_t>::max());
auto low = static_cast<int64_t>(std::numeric_limits<int32_t>::lowest());
LUCI_ASSERT(pl <= max, "paddings is over 32 bit limit");
LUCI_ASSERT(pl >= low, "paddings is over 32 bit limit");
LUCI_ASSERT(pr <= max, "paddings is over 32 bit limit");
LUCI_ASSERT(pr >= low, "paddings is over 32 bit limit");
value += static_cast<int32_t>(pl); // left
value += static_cast<int32_t>(pr); // right
if (paddings->dtype() == S32)
{
value += paddings->at<S32>(idx + 0); // left
value += paddings->at<S32>(idx + 1); // right
}
else
{
auto pl = paddings->at<S64>(idx + 0);
auto pr = paddings->at<S64>(idx + 1);
auto max = static_cast<int64_t>(std::numeric_limits<int32_t>::max());
auto low = static_cast<int64_t>(std::numeric_limits<int32_t>::lowest());
LUCI_ASSERT(pl <= max, "paddings is over 32 bit limit");
LUCI_ASSERT(pl >= low, "paddings is over 32 bit limit");
LUCI_ASSERT(pr <= max, "paddings is over 32 bit limit");
LUCI_ASSERT(pr >= low, "paddings is over 32 bit limit");
value += static_cast<int32_t>(pl); // left
value += static_cast<int32_t>(pr); // right
}
output_shape.dim(ni) = value;
}
output_shape.dim(ni) = value;
}

return loco::NodeShape{output_shape};
}

Expand Down Expand Up @@ -2599,7 +2605,8 @@ bool CircleShapeInferenceRule::infer(const loco::Node *node, loco::NodeShape &sh
else
shape = circle_node->accept(&alg);
}

VERBOSE(l, 1) << "[icodo] shape status: " << is_shape_undefined << ", " << is_shape_none << ", "
<< is_scalar;
VERBOSE(l, 1) << "[luci] shape: " << circle_node->name();
VERBOSE(l, 1) << " own_shape: " << own_shape(circle_node)
<< " -> infer: " << shape.as<loco::TensorShape>();
Expand Down
41 changes: 41 additions & 0 deletions compiler/luci/service/src/Nodes/CirclePad.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

#include "luci/Service/CircleNodeClone.h"

#include "luci/Service/CircleShapeInference.h"

#include <gtest/gtest.h>

TEST(CloneNodeTest, clone_Pad)
Expand All @@ -31,3 +33,42 @@ TEST(CloneNodeTest, clone_Pad)
auto cloned_pad = dynamic_cast<luci::CirclePad *>(cloned);
ASSERT_NE(nullptr, cloned_pad);
}

TEST(ShapeRuleTest, padding_dynamic_shape)
{
luci::CirclePad pad;
luci::CircleInput input;
// Use circle input as paddings
luci::CircleConst padddings;

loco::TensorShape shape;
luci::sinf::Rule shape_inf_rule;

input.shape({1, 2, 3, 4});
input.shape_status(luci::ShapeStatus::VALID);
input.dim(2).unset();

padddings.dtype(loco::DataType::S64);
padddings.shape({4, 2});
padddings.shape_status(luci::ShapeStatus::VALID);

const loco::DataType S64 = loco::DataType::S64;
uint32_t t = 64 * 8;
padddings.size<S64>(t);

pad.input(&input);
pad.paddings(&padddings);

ASSERT_TRUE(shape_inf_rule.infer(&pad, shape));
ASSERT_EQ(shape.rank(), 4);
ASSERT_TRUE(shape.dim(0).known());
ASSERT_TRUE(shape.dim(1).known());
ASSERT_FALSE(shape.dim(2).known());
ASSERT_TRUE(shape.dim(3).known());

ASSERT_EQ(1, shape.dim(0).value());
ASSERT_EQ(2, shape.dim(1).value());
ASSERT_EQ(0, shape.dim(2).value());
ASSERT_EQ(4, shape.dim(3).value());
pad.drop();
}
8 changes: 0 additions & 8 deletions compiler/luci/tester/src/WriteTester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ void show_error_message(const char *progname, std::ostream &os, const std::strin
struct CircleExpContract : public luci::CircleExporter::Contract
{
public:
CircleExpContract(loco::Graph *graph, const std::string &filename)
: _graph(graph), _filepath(filename)
{
// NOTHING TO DO
}
CircleExpContract(luci::Module *module, const std::string &filename)
: _module(module), _filepath(filename)
{
Expand All @@ -55,15 +50,12 @@ struct CircleExpContract : public luci::CircleExporter::Contract
virtual ~CircleExpContract() = default;

public:
loco::Graph *graph(void) const final { return _graph; }

luci::Module *module(void) const final { return _module; }

public:
bool store(const char *ptr, const size_t size) const final;

private:
loco::Graph *_graph{nullptr};
luci::Module *_module{nullptr};
const std::string _filepath;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ template <typename T> void evalComparisonGeneric(OMRuntimeKernel *runtime_kernel
}
}

template <typename T>
void evalQuantizedComparisonGeneric(OMRuntimeKernel *runtime_kernel, bool F(T, T))
template <typename T, typename AccType>
void evalQuantizedComparisonGeneric(OMRuntimeKernel *runtime_kernel, bool F(AccType, AccType))
{
const circle::Tensor *input1 = nullptr;
const circle::Tensor *input2 = nullptr;
Expand Down
8 changes: 4 additions & 4 deletions onert-micro/onert-micro/include/pal/common/PALComparisons.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ inline void ComparisonNoScaling(const int64_t flat_size, const T *input1_data, c
}
}

template <typename T>
template <typename T, typename AccType>
inline void BroadcastComparison4DSlowWithScaling(
const core::ComparisonParams &op_params, const core::OMRuntimeShape &unextended_input1_shape,
const T *input1_data, const core::OMRuntimeShape &unextended_input2_shape, const T *input2_data,
const core::OMRuntimeShape &unextended_output_shape, bool *output_data, bool F(T, T))
const core::OMRuntimeShape &unextended_output_shape, bool *output_data, bool F(AccType, AccType))
{
const BroadcastComparison4DSlowCommon dims = BroadcastComparison4DSlowPreprocess(
unextended_input1_shape, unextended_input2_shape, unextended_output_shape);
Expand Down Expand Up @@ -118,10 +118,10 @@ inline void BroadcastComparison4DSlowWithScaling(
}
}

template <typename T>
template <typename T, typename AccType>
inline void ComparisonWithScaling(const core::ComparisonParams &op_params, const int64_t flat_size,
const T *input1_data, const T *input2_data, bool *output_data,
bool F(T, T))
bool F(AccType, AccType))
{
int left_shift = op_params.left_shift;
int32_t input1_offset = op_params.input1_offset;
Expand Down
Loading

0 comments on commit c7a4dca

Please sign in to comment.