Skip to content

Commit

Permalink
[luci] Add UNPACK in QuantizeWithMinMaxPass (Samsung#7284)
Browse files Browse the repository at this point in the history
* [luci] Add UNPACK in QuantizeWithMinMaxPass

This makes QuantizeWithMinMaxPass process UNPACK op.

Signed-off-by: Hyun Sik Yoon <[email protected]>

* Add code for Verifier

* null check
  • Loading branch information
hyunsik-yoon authored Jul 22, 2021
1 parent 97bad4e commit 3026278
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 0 deletions.
16 changes: 16 additions & 0 deletions compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,21 @@ struct QuantizeSpecialActivation final : public luci::CircleNodeMutableVisitor<v
auto split = loco::must_cast<luci::CircleSplit *>(node->input());
auto input = loco::must_cast<luci::CircleNode *>(split->input());
auto i_qparam = input->quantparam();
assert(i_qparam);
assert(i_qparam->scale.size() == 1); // FIX_CALLER_UNLESS
assert(i_qparam->zerop.size() == 1); // FIX_CALLER_UNLESS
auto i_scale = i_qparam->scale[0];
auto i_zp = i_qparam->zerop[0];

set_act_qparam(node, i_scale, i_zp);
}

void visit(luci::CircleUnpackOut *node)
{
auto unpack = loco::must_cast<luci::CircleUnpack *>(node->input());
auto input = loco::must_cast<luci::CircleNode *>(unpack->value());
auto i_qparam = input->quantparam();
assert(i_qparam);
assert(i_qparam->scale.size() == 1); // FIX_CALLER_UNLESS
assert(i_qparam->zerop.size() == 1); // FIX_CALLER_UNLESS
auto i_scale = i_qparam->scale[0];
Expand Down Expand Up @@ -1085,6 +1100,7 @@ void quantize_const_inputs(luci::CircleNode *node, loco::DataType output_type)
case luci::CircleOpcode::SQRT:
case luci::CircleOpcode::SUB:
case luci::CircleOpcode::TANH:
case luci::CircleOpcode::UNPACK:
// Quantize all const inputs using their values
for (uint32_t i = 0; i < arity; i++)
{
Expand Down
53 changes: 53 additions & 0 deletions compiler/luci/pass/src/QuantizedModelVerifier.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,35 @@ class ResizeNearestNeighborTestGraph final : public luci::test::TestIOGraph
luci::CircleConst *_size = nullptr;
};

class UnpackTestGraph final : public luci::test::TestIOGraph
{
public:
void init(void)
{
TestIOGraph::init({1, 32}, {32});
_unpack = g()->nodes()->create<luci::CircleUnpack>();
{
_unpack->value(input());
_unpack->axis(0);
_unpack->num(1);
}
_unpack_o1 = g()->nodes()->create<luci::CircleUnpackOut>();
{
_unpack_o1->input(_unpack);
_unpack_o1->index(0);
}

output()->from(_unpack_o1);

set_minmax_to_non_const(g(), -1, 1);
}

private:
luci::CircleUnpack *_unpack = nullptr;
luci::CircleUnpackOut *_unpack_o1 = nullptr;
luci::CircleConst *_unpack_dim = nullptr;
};

} // namespace

// Quantize and verify with given configurations
Expand Down Expand Up @@ -1916,6 +1945,30 @@ TEST(QuantizedModelVerifierTest, ResizeNearestNeighbor_wrong_granularity_NEG)
SUCCEED();
}

TEST(QuantizedModelVerifierTest, Unpack)
{
TEST_WITH_GRAPH(UnpackTestGraph, Type::U8, Granularity::LayerWise);
TEST_WITH_GRAPH(UnpackTestGraph, Type::U8, Granularity::ChannelWise);
TEST_WITH_GRAPH(UnpackTestGraph, Type::S16, Granularity::ChannelWise);
SUCCEED();
}

TEST(QuantizedModelVerifierTest, Unpack_wrong_type_NEG)
{
TEST_WITH_WRONG_TYPE(UnpackTestGraph, Type::U8, Granularity::LayerWise, Type::S16);
TEST_WITH_WRONG_TYPE(UnpackTestGraph, Type::U8, Granularity::ChannelWise, Type::S16);
TEST_WITH_WRONG_TYPE(UnpackTestGraph, Type::S16, Granularity::ChannelWise, Type::U8);
SUCCEED();
}

TEST(QuantizedModelVerifierTest, Unpack_wrong_granularity_NEG)
{
TEST_WITH_WRONG_GRANULARITY(UnpackTestGraph, Type::U8, Granularity::LayerWise);
TEST_WITH_WRONG_GRANULARITY(UnpackTestGraph, Type::U8, Granularity::ChannelWise);
TEST_WITH_WRONG_GRANULARITY(UnpackTestGraph, Type::S16, Granularity::ChannelWise);
SUCCEED();
}

#undef TEST_WITH_GRAPH
#undef TEST_WITH_WRONG_TYPE
#undef TEST_WITH_WRONG_GRANULARITY
13 changes: 13 additions & 0 deletions compiler/luci/pass/src/VerifyQuantizedNodeChannelWiseGranularity.h
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,19 @@ struct VerifyQuantizedNodeChannelWiseGranularity final : public luci::CircleNode
return true;
}

bool visit(const luci::CircleUnpack *node)
{
// node's output is the input of CircleUnpackOut, thus not quantized
RETURN_FALSE_UNLESS(is_lwq(node->value()));
return true;
}

bool visit(const luci::CircleUnpackOut *node)
{
RETURN_FALSE_UNLESS(is_lwq(node));
return true;
}

// TODO: Implement more Ops

bool visit(const luci::CircleNode *) { return true; }
Expand Down
13 changes: 13 additions & 0 deletions compiler/luci/pass/src/VerifyQuantizedNodeLayerWiseGranularity.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,19 @@ struct VerifyQuantizedNodeLayerWiseGranularity final : public luci::CircleNodeVi
return true;
}

bool visit(const luci::CircleUnpack *node)
{
// node's output is the input of CircleUnpackOut, thus not quantized
RETURN_FALSE_UNLESS(is_lwq(node->value()));
return true;
}

bool visit(const luci::CircleUnpackOut *node)
{
RETURN_FALSE_UNLESS(is_lwq(node));
return true;
}

// TODO: Implement more Ops

bool visit(const luci::CircleNode *) { return true; }
Expand Down
20 changes: 20 additions & 0 deletions compiler/luci/pass/src/VerifyQuantizedNodeS16Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,26 @@ struct VerifyQuantizedNodeS16Type final : public luci::CircleNodeVisitor<bool>
return true;
}

bool visit(const luci::CircleUnpack *node)
{
// node's output is the input of CircleUnpackOut, thus not quantized
RETURN_FALSE_UNLESS(has_type(node->value(), Type::S16))
return true;
}

bool visit(const luci::CircleUnpackOut *node)
{
RETURN_FALSE_UNLESS(has_type(node, Type::S16))

// UnpackOut has the same qparam with the input of Unpack
auto Unpack = loco::must_cast<luci::CircleUnpack *>(node->input());
auto input = loco::must_cast<luci::CircleNode *>(Unpack->value());
assert(node->quantparam() && input->quantparam());
RETURN_FALSE_UNLESS(node->quantparam()->scale[0] == input->quantparam()->scale[0]);
RETURN_FALSE_UNLESS(node->quantparam()->zerop[0] == input->quantparam()->zerop[0]);
return true;
}

// TODO: Implement more Ops

bool visit(const luci::CircleNode *) { return true; }
Expand Down
20 changes: 20 additions & 0 deletions compiler/luci/pass/src/VerifyQuantizedNodeU8Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,26 @@ struct VerifyQuantizedNodeU8Type final : public luci::CircleNodeVisitor<bool>
return true;
}

bool visit(const luci::CircleUnpack *node)
{
// node's output is the input of CircleUnpackOut, thus not quantized
RETURN_FALSE_UNLESS(has_type(node->value(), Type::U8))
return true;
}

bool visit(const luci::CircleUnpackOut *node)
{
RETURN_FALSE_UNLESS(has_type(node, Type::U8))

// UnpackOut has the same qparam with the input of Unpack
auto Unpack = loco::must_cast<luci::CircleUnpack *>(node->input());
auto input = loco::must_cast<luci::CircleNode *>(Unpack->value());
assert(node->quantparam() && input->quantparam());
RETURN_FALSE_UNLESS(node->quantparam()->scale[0] == input->quantparam()->scale[0]);
RETURN_FALSE_UNLESS(node->quantparam()->zerop[0] == input->quantparam()->zerop[0]);
return true;
}

// TODO: Implement more Ops

bool visit(const luci::CircleNode *) { return true; }
Expand Down

0 comments on commit 3026278

Please sign in to comment.