Skip to content

Commit

Permalink
[luci] Introduce Compress weights pass
Browse files Browse the repository at this point in the history
This commit introduces CopressWeightsPass for Conv2D

ONE-DCO-1.0-Signed-off-by: Vyacheslav Bazhenov <[email protected]>
  • Loading branch information
Vyacheslav Bazhenov committed Aug 9, 2024
1 parent 98ed924 commit 1e12f94
Show file tree
Hide file tree
Showing 19 changed files with 531 additions and 8 deletions.
4 changes: 4 additions & 0 deletions compiler/circle2circle/src/Circle2Circle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ int entry(int argc, char **argv)
"This will convert single input Transpose to Reshape");
add_switch(arser, "--expand_broadcast_const", "This will expand broadcastable constant inputs");
add_switch(arser, "--unroll_unidirseqlstm", "Unroll UnidirectionalSequenceLSTM operator.");
add_switch(arser, "--compress_weights_huffman",
"Loseless weights compression with Huffman encoding.");
add_switch(arser, "--convert_nchw_to_nhwc",
"Experimental: This will convert NCHW operators to NHWC under the assumption that "
"input model is NCHW.");
Expand Down Expand Up @@ -405,6 +407,8 @@ int entry(int argc, char **argv)
options->enable(Algorithms::ExpandBroadcastConst);
if (arser.get<bool>("--unroll_unidirseqlstm"))
options->enable(Algorithms::UnrollUnidirSeqLSTM);
if (arser.get<bool>("--compress_weights_huffman"))
options->enable(Algorithms::CompressWeightsHuffman);

// NOTE Experimental options; these will be removed someday
// Add experimental options here
Expand Down
8 changes: 4 additions & 4 deletions compiler/luci/export/src/CircleBuiltinTypesExtractor.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@ class BuiltinOptionsExtractor final
// flatbuffers::Offset<void> visit(luci::CircleConst *)
flatbuffers::Offset<void> visit(luci::CircleConv2D *node)
{
return circle::CreateConv2DOptions(_builder, getOpPadding(node->padding()), node->stride()->w(),
node->stride()->h(),
to_circle_actfunc(node->fusedActivationFunction()),
node->dilation()->w(), node->dilation()->h())
return circle::CreateConv2DOptions(
_builder, getOpPadding(node->padding()), node->stride()->w(), node->stride()->h(),
to_circle_actfunc(node->fusedActivationFunction()), node->dilation()->w(),
node->dilation()->h(), to_circle_weightcompressiontype(node->weightCompression()))
.Union();
}
flatbuffers::Offset<void> visit(luci::CircleCos *)
Expand Down
13 changes: 13 additions & 0 deletions compiler/luci/export/src/CircleExporterUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@

namespace luci
{
circle::WeightCompressionType to_circle_weightcompressiontype(luci::WeightCompression type)
{
switch (type)
{
case luci::WeightCompression::NONE:
return circle::WeightCompressionType_NONE;
case luci::WeightCompression::HUFFMAN:
return circle::WeightCompressionType_Huffman;
default:
INTERNAL_EXN_V("trying to convert unsupported luci::WeightCompression",
oops::to_uint32(type));
}
}

circle::ActivationFunctionType to_circle_actfunc(luci::FusedActFunc func)
{
Expand Down
1 change: 1 addition & 0 deletions compiler/luci/export/src/CircleExporterUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
namespace luci
{

circle::WeightCompressionType to_circle_weightcompressiontype(luci::WeightCompression type);
circle::ActivationFunctionType to_circle_actfunc(luci::FusedActFunc func);
circle::TensorType to_circle_tensortype(loco::DataType type);
circle::MirrorPadMode to_circle_mirrorpadmode(luci::MirrorPadMode mode);
Expand Down
4 changes: 4 additions & 0 deletions compiler/luci/export/src/CircleTensorExporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,8 @@ bool has_same_values(luci::CircleConst *lhs, luci::CircleConst *rhs)
return has_same_elements<loco::DataType::S4>(lhs, rhs);

case loco::DataType::S8:
if (lhs->size<loco::DataType::S8>() != rhs->size<loco::DataType::S8>())
return false;
return has_same_elements<loco::DataType::S8>(lhs, rhs);

case loco::DataType::S16:
Expand All @@ -574,6 +576,8 @@ bool has_same_values(luci::CircleConst *lhs, luci::CircleConst *rhs)
return has_same_elements<loco::DataType::U4>(lhs, rhs);

case loco::DataType::U8:
if (lhs->size<loco::DataType::U8>() != rhs->size<loco::DataType::U8>())
return false;
return has_same_elements<loco::DataType::U8>(lhs, rhs);

case loco::DataType::BOOL:
Expand Down
32 changes: 32 additions & 0 deletions compiler/luci/import/include/luci/Import/CircleImporterUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef __CIRCLE_IMPORTER_UTILS_H__
#define __CIRCLE_IMPORTER_UTILS_H__

#include <luci/IR/CircleNodes.h>

#include <loco.h>

#include <mio/circle/schema_generated.h>

namespace luci
{
luci::WeightCompression from_circle_weightcompressiontype(circle::WeightCompressionType type);

} // namespace luci

#endif // __CIRCLE_IMPORTER_UTILS_H__
36 changes: 36 additions & 0 deletions compiler/luci/import/src/CircleImporterUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "luci/Import/CircleImporterUtils.h"

#include <oops/InternalExn.h>

namespace luci
{
luci::WeightCompression from_circle_weightcompressiontype(circle::WeightCompressionType type)
{
switch (type)
{
case circle::WeightCompressionType_NONE:
return luci::WeightCompression::NONE;
case circle::WeightCompressionType_Huffman:
return luci::WeightCompression::HUFFMAN;
default:
INTERNAL_EXN_V("trying to convert unsupported luci::WeightCompression",
oops::to_uint32(type));
}
}
} // namespace luci
3 changes: 2 additions & 1 deletion compiler/luci/import/src/Nodes/CircleConv2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
* limitations under the License.
*/

#include "luci/Import/CircleImporterUtils.h"
#include "luci/Import/Nodes/CircleConv2D.h"

#include <luci/IR/Nodes/CircleConv2D.h>

#include <loco.h>

#include <cassert>
Expand Down Expand Up @@ -49,6 +49,7 @@ CircleNode *CircleConv2DGraphBuilder::build_node(const circle::OperatorT &op,
node->fusedActivationFunction(luci_actfunc(options->fused_activation_function));
node->dilation()->w(options->dilation_w_factor);
node->dilation()->h(options->dilation_h_factor);
node->weightCompression(from_circle_weightcompressiontype(options->weight_compression_type));

return node;
}
Expand Down
33 changes: 33 additions & 0 deletions compiler/luci/lang/include/luci/IR/AttrWeightCompression.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef __LUCI_IR_ATTRWEIGHTCOMPRESSION_H__
#define __LUCI_IR_ATTRWEIGHTCOMPRESSION_H__

namespace luci
{

enum class WeightCompression
{
UNDEFINED, // This is not defined by TFLite or Circle. This was added to
// prevent programming error.
NONE,
HUFFMAN
};

} // namespace luci

#endif // __LUCI_IR_ATTRWEIGHTCOMPRESSION_H__
20 changes: 19 additions & 1 deletion compiler/luci/lang/include/luci/IR/CircleNodeMixins.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define __LUCI_IR_CIRCLE_NODE_MIXINS_H__

#include "luci/IR/AttrFusedActFunc.h"
#include "luci/IR/AttrWeightCompression.h"

#include <loco/IR/Node.h>
#include <loco/IR/NodeMixins.h>
Expand All @@ -31,11 +32,28 @@ namespace luci
enum class CircleNodeTrait
{
FusedActFunc,
Bias
Bias,
WeightCompression
};

template <CircleNodeTrait T> class CircleNodeMixin;

template <> class CircleNodeMixin<CircleNodeTrait::WeightCompression>
{
public:
CircleNodeMixin() = default;

public:
WeightCompression weightCompression() const { return _weight_compression; }
void weightCompression(WeightCompression weight_compression)
{
_weight_compression = weight_compression;
}

private:
WeightCompression _weight_compression = WeightCompression::UNDEFINED;
};

template <> class CircleNodeMixin<CircleNodeTrait::FusedActFunc>
{
public:
Expand Down
5 changes: 5 additions & 0 deletions compiler/luci/lang/include/luci/IR/Nodes/CircleConst.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef __LUCI_IR_CIRCLECONST_H__
#define __LUCI_IR_CIRCLECONST_H__

#include "luci/IR/AttrWeightCompression.h"
#include "luci/IR/CircleNodeDecl.h"
#include "luci/IR/CircleOpcode.h"

Expand All @@ -34,6 +35,9 @@ namespace luci
class CircleConst final : public FixedArityNode<0, CircleNodeImpl<CircleOpcode::CIRCLECONST>>
{
public:
template <loco::DataType DT> WeightCompression compression(void) const;
template <loco::DataType DT> void compression(WeightCompression c);

template <loco::DataType DT> uint32_t size(void) const;
template <loco::DataType DT> void size(uint32_t size);
template <loco::DataType DT> const typename loco::DataTypeImpl<DT>::Type &at(uint32_t n) const;
Expand All @@ -46,6 +50,7 @@ class CircleConst final : public FixedArityNode<0, CircleNodeImpl<CircleOpcode::
std::vector<uint8_t> _data;
// TODO use _data for STRING and remove _strings
std::vector<std::string> _strings; // for STRING type
WeightCompression _compression{WeightCompression::NONE};
};

} // namespace luci
Expand Down
3 changes: 2 additions & 1 deletion compiler/luci/lang/include/luci/IR/Nodes/CircleConv2D.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ namespace luci
*/
class CircleConv2D final : public FixedArityNode<3, CircleNodeImpl<CircleOpcode::CONV_2D>>,
public CircleNodeMixin<CircleNodeTrait::FusedActFunc>,
public CircleNodeMixin<CircleNodeTrait::Bias>
public CircleNodeMixin<CircleNodeTrait::Bias>,
public CircleNodeMixin<CircleNodeTrait::WeightCompression>
{
public:
loco::Node *input(void) const { return at(0)->node(); }
Expand Down
13 changes: 13 additions & 0 deletions compiler/luci/lang/src/Nodes/CircleConst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@

namespace luci
{
template <loco::DataType DT> WeightCompression CircleConst::compression(void) const
{
assert(dtype() == DT);
return _compression;
}

template <loco::DataType DT> void CircleConst::compression(luci::WeightCompression c)
{
assert(dtype() == DT);
_compression = c;
}

template <loco::DataType DT> uint32_t CircleConst::size(void) const
{
Expand Down Expand Up @@ -63,6 +74,8 @@ template <loco::DataType DT> typename loco::DataTypeImpl<DT>::Type &CircleConst:
}

#define INSTANTIATE(DT) \
template WeightCompression CircleConst::compression<DT>(void) const; \
template void CircleConst::compression<DT>(WeightCompression); \
template uint32_t CircleConst::size<DT>(void) const; \
template void CircleConst::size<DT>(uint32_t); \
template const typename loco::DataTypeImpl<DT>::Type &CircleConst::at<DT>(uint32_t) const; \
Expand Down
1 change: 1 addition & 0 deletions compiler/luci/pass/include/luci/CircleOptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class CircleOptimizer final
UnrollUnidirSeqLSTM,
XpSepActFromTransposeConv,
RemoveGatherGuard,
CompressWeightsHuffman
};

enum AlgorithmParameters
Expand Down
39 changes: 39 additions & 0 deletions compiler/luci/pass/include/luci/Pass/CompressWeightsPass.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef __LUCI_COMPRESS_WEIGHTS_PASS_H__
#define __LUCI_COMPRESS_WEIGHTS_PASS_H__

#include <logo/Pass.h>

namespace luci
{

/**
* @brief Class to generate FC/CONV with compressed weights
*
* To see the target Op pattern, please visit implementation.
*/
struct CompressWeightsPass final : public logo::Pass
{
const char *name(void) const final { return "luci::CompressWeightsPass"; }

bool run(loco::Graph *g) final;
};

} // namespace luci

#endif // __LUCI_COMPRESS_WEIGHTS_PASS_H__
6 changes: 5 additions & 1 deletion compiler/luci/pass/src/CircleOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
#include "luci/Pass/DecomposeSoftmaxPass.h"
#include "luci/Pass/UnrollUnidirectionalSequenceLSTMPass.h"
#include "luci/Pass/XpSepActFromTransposeConvPass.h"
#include "luci/Pass/CompressWeightsPass.h"
// TODO add more passes

#include "luci/Pass/CircleShapeInferencePass.h"
Expand Down Expand Up @@ -534,7 +535,10 @@ void CircleOptimizer::optimize(loco::Graph *g) const
{
phase.emplace_back(std::make_unique<luci::UnrollUnidirectionalSequenceLSTMPass>());
}

if (_options->query(Options::Algorithm::CompressWeightsHuffman))
{
phase.emplace_back(std::make_unique<luci::CompressWeightsPass>());
}
// NOTE Experimental options; these will be removed someday
// Add experimental options here
if (_options->query(Options::Algorithm::XpSepActFromTransposeConv))
Expand Down
Loading

0 comments on commit 1e12f94

Please sign in to comment.