Skip to content

Commit

Permalink
Customizable PassPipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
v-Golubev committed Nov 14, 2023
1 parent 2ffd19a commit b1165f9
Show file tree
Hide file tree
Showing 15 changed files with 246 additions and 180 deletions.
22 changes: 1 addition & 21 deletions src/common/snippets/include/snippets/lowered/pass/pass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,32 +35,12 @@ class Pass {
return get_type_info_static();
}

const char* get_type_name() const {
std::string get_name() const {
return get_type_info().name;
}

virtual bool run(lowered::LinearIR& linear_ir) = 0;
};

class PassPipeline {
public:
PassPipeline() = default;

void register_pass(const std::shared_ptr<Pass>& pass);

template<typename T, class... Args>
void register_pass(Args&&... args) {
static_assert(std::is_base_of<Pass, T>::value, "Pass not derived from lowered::Pass");
auto pass = std::make_shared<T>(std::forward<Args>(args)...);
register_pass(pass);
}

void run(lowered::LinearIR& linear_ir) const;

private:
std::vector<std::shared_ptr<Pass>> m_passes;
};

} // namespace pass
} // namespace lowered
} // namespace snippets
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (C) 2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include "pass.hpp"
#include "snippets/pass/pass_position.hpp"

namespace ov {
namespace snippets {
namespace lowered {
namespace pass {
class PassPipeline {
public:
PassPipeline() = default;

void run(lowered::LinearIR& linear_ir) const;
void register_pass(const std::shared_ptr<Pass>& pass);

template<typename T, class... Args>
void register_pass(Args&&... args) {
static_assert(std::is_base_of<Pass, T>::value, "Pass not derived from lowered::Pass");
auto pass = std::make_shared<T>(std::forward<Args>(args)...);
register_pass(pass);
}

struct PositionedPass {
ov::snippets::pass::PassPosition position;
std::shared_ptr<Pass> pass;
PositionedPass(ov::snippets::pass::PassPosition arg_pos, std::shared_ptr<Pass> arg_pass)
: position(std::move(arg_pos)), pass(std::move(arg_pass)) {
}
};

template <typename T, class Pos, class... Args, std::enable_if<std::is_same<ov::snippets::pass::PassPosition, Pos>::value, bool>() = true>
void register_pass(const ov::snippets::pass::PassPosition& position, Args&&... args) {
static_assert(std::is_base_of<Pass, T>::value, "Attempt to insert pass that is not derived from Pass");
auto pass = std::make_shared<T>(std::forward<Args>(args)...);
insert_pass_instance(position, pass);
}

void register_positioned_passes(const std::vector<PositionedPass>& pos_passes);

protected:
void insert_pass_instance(const ov::snippets::pass::PassPosition& position, const std::shared_ptr<Pass>& pass);

private:
std::vector<std::shared_ptr<Pass>> m_passes;
};

} // namespace pass
} // namespace lowered
} // namespace snippets
} // namespace ov
19 changes: 8 additions & 11 deletions src/common/snippets/include/snippets/op/subgraph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
#pragma once

#include <memory>

#include <openvino/core/model.hpp>
#include <openvino/op/util/sub_graph_base.hpp>
#include "openvino/op/op.hpp"

#include "openvino/core/rt_info.hpp"
#include "openvino/op/op.hpp"
#include "snippets/generator.hpp"
#include "snippets/lowered/pass/pass.hpp"
#include "snippets/lowered/pass/pass_pipeline.hpp"
#include "snippets/pass/manager.hpp"
#include "snippets/shape_inference/shape_inference.hpp"
#include "snippets/lowered/pass/pass.hpp"

#include "snippets/generator.hpp"

namespace ov {
namespace snippets {
Expand Down Expand Up @@ -104,13 +104,11 @@ class Subgraph : public ov::op::util::SubGraphOp {
const std::vector<ov::element::Type>& input_precisions = {},
const std::vector<ov::element::Type>& output_precisions = {},
const std::vector<pass::Manager::PositionedPass>& data_flow_passes = {},
const lowered::pass::PassPipeline& control_flow_passes_pre_common = {},
const lowered::pass::PassPipeline& control_flow_passes_post_common = {},
const std::vector<lowered::pass::PassPipeline::PositionedPass>& control_flow_passes = {},
const std::shared_ptr<IShapeInferSnippetsFactory>& factory = nullptr,
const void* compile_params = nullptr);

snippets::Schedule generate_from_linear_ir(const lowered::pass::PassPipeline& backend_passes_pre_common = {},
const lowered::pass::PassPipeline& backend_passes_post_common = {},
snippets::Schedule generate_from_linear_ir(const std::vector<lowered::pass::PassPipeline::PositionedPass>& control_flow_passes = {},
const void* compile_params = nullptr) const;
IShapeInferSnippets::Result shape_infer(const std::vector<VectorDimsRef>& input_shapes);

Expand Down Expand Up @@ -150,8 +148,7 @@ class Subgraph : public ov::op::util::SubGraphOp {
private:
void control_flow_transformations(lowered::LinearIR& linear_ir,
LoweringResult& lowering_result,
const lowered::pass::PassPipeline& backend_passes_pre_common,
const lowered::pass::PassPipeline& backend_passes_post_common) const;
const std::vector<lowered::pass::PassPipeline::PositionedPass>& control_flow_passes) const;
void init_config();
// Count of Subgraph virtual ports:
// - Potential non-scalar Constants that will be created after some transformations (At the moment it's relevant only for FakeQuantize decomposition)
Expand Down
35 changes: 5 additions & 30 deletions src/common/snippets/include/snippets/pass/manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

#pragma once

#include <typeinfo>

#include "openvino/pass/manager.hpp"
#include "openvino/pass/pass.hpp"
#include "openvino/pass/validate.hpp"

#include <typeinfo>

#include "pass_position.hpp"

namespace ov {
namespace snippets {
Expand All @@ -24,31 +24,6 @@ class Manager : public ov::pass::Manager {
~Manager() override = default;
using PassBase = ov::pass::PassBase;
using Validate = ov::pass::Validate;
/**
* @brief PassPosition describes a particular position in a transformation pipeline,
* where a new transformation should be inserted.
* @param pass_name name of the anchor pass, the new pass will be inserted before/after it.
* Empty pass_name could mean either beginning or the end of the pipeline depending on the `after` flag.
* No default value. Note that pass names namespaces are not supported, ov::PassName and snippets::PassName
* are considered identical.
* @param after `true` if the new pass should be inserted before the anchor pass, `false` otherwise (default).
* If `pass_name` is empty, `true` means the end, and `false` - the beginning of the pipeline.
* @param pass_instance the number of the pass with matching `pass_name` to be considered as the anchor pass.
* 0 (default) means the first pass with `pass_name` will be considered as the anchor pass.
* @ingroup snippets
*/
class PassPosition {
public:
enum class Place {Before, After, PipelineStart, PipelineEnd};
using PassListType = std::vector<std::shared_ptr<ov::pass::PassBase>>;
explicit PassPosition(Place pass_place);
explicit PassPosition(Place pass_place, std::string pass_name, size_t pass_instance = 0);
PassListType::const_iterator get_insert_position(const PassListType& pass_list) const;
private:
const std::string m_pass_name;
const size_t m_pass_instance{0};
const Place m_place{Place::Before};
};
struct PositionedPass {
PassPosition position;
std::shared_ptr<PassBase> pass;
Expand All @@ -65,7 +40,7 @@ class Manager : public ov::pass::Manager {
std::shared_ptr<T> register_pass(const PassPosition& position, Args&&... args) {
static_assert(std::is_base_of<PassBase, T>::value, "Attempt to insert pass that is not derived from PassBase");
auto pass = std::make_shared<T>(std::forward<Args>(args)...);
auto rc = insert_pass_instance(position, pass);
auto rc = insert_pass_instance(position, pass);
rc->set_pass_config(m_pass_config);
if (!m_pass_config->is_enabled<T>()) {
m_pass_config->disable<T>();
Expand All @@ -77,7 +52,7 @@ class Manager : public ov::pass::Manager {
void register_positioned_passes(const std::vector<PositionedPass>& pos_passes);

protected:
std::shared_ptr<Manager::PassBase> insert_pass_instance(const PassPosition& position, const std::shared_ptr<PassBase>& pass);
std::shared_ptr<PassBase> insert_pass_instance(const PassPosition& position, const std::shared_ptr<PassBase>& pass);
};

} // namespace pass
Expand Down
83 changes: 83 additions & 0 deletions src/common/snippets/include/snippets/pass/pass_position.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include "openvino/pass/manager.hpp"
#include "openvino/pass/pass.hpp"
#include "openvino/pass/validate.hpp"

#include <typeinfo>


namespace ov {
namespace snippets {
namespace pass {
/**
* @brief PassPosition describes a particular position in a transformation pipeline,
* where a new transformation should be inserted.
* @param pass_name name of the anchor pass, the new pass will be inserted before/after it.
* Empty pass_name could mean either beginning or the end of the pipeline depending on the `after` flag.
* No default value. Note that pass names namespaces are not supported, ov::PassName and snippets::PassName
* are considered identical.
* @param after `true` if the new pass should be inserted before the anchor pass, `false` otherwise (default).
* If `pass_name` is empty, `true` means the end, and `false` - the beginning of the pipeline.
* @param pass_instance the number of the pass with matching `pass_name` to be considered as the anchor pass.
* 0 (default) means the first pass with `pass_name` will be considered as the anchor pass.
* @ingroup snippets
*/
class PassPosition {
public:
enum class Place {Before, After, PipelineStart, PipelineEnd};
explicit PassPosition(Place pass_place);
explicit PassPosition(Place pass_place, std::string pass_name, size_t pass_instance = 0);

template <typename PassBase>
typename std::vector<std::shared_ptr<PassBase>>::const_iterator
get_insert_position(const std::vector<std::shared_ptr<PassBase>>& pass_list) const {
size_t pass_count = 0;
auto match = [this, &pass_count](const std::shared_ptr<PassBase>& p) {
auto name = p->get_name();
// Note that MatcherPass and ModelPass currently have different naming policies:
// - MatcherPass have names without namespaces, e.g. ConvertToSwishCPU
// - Similar ModelPass name includes namespaces: ov::snippets::pass::ConvertToSwishCPU
// So we have to remove everything before the last ':', and ':' itself
if (name.size() > m_pass_name.size()) {
const auto pos = name.find_last_of(':');
if (pos == std::string::npos)
return false;
name = name.substr(pos + 1);
}
if (name == m_pass_name) {
if (m_pass_instance == pass_count)
return true;
pass_count++;
}
return false;
};

switch (m_place) {
case Place::PipelineStart:
return pass_list.cbegin();
case Place::PipelineEnd:
return pass_list.cend();
case Place::Before:
case Place::After: {
auto insert_it = std::find_if(pass_list.cbegin(), pass_list.cend(), match);
OPENVINO_ASSERT(insert_it != pass_list.cend(), "snippets::pass::Manager failed to find pass ", m_pass_name);
return m_place == Place::After ? std::next(insert_it) : insert_it;
}
default:
OPENVINO_THROW("Unsupported Place type in PassPosition::get_insert_position");
}
}

private:
const std::string m_pass_name;
const size_t m_pass_instance{0};
const Place m_place{Place::Before};
};
} // namespace pass
} // namespace snippets
} // namespace ov
7 changes: 3 additions & 4 deletions src/common/snippets/src/generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,23 @@

#include "snippets/generator.hpp"

#include "snippets/itt.hpp"
#include "snippets/lowered/linear_ir.hpp"
#include "snippets/lowered/pass/assign_registers.hpp"
#include "snippets/lowered/pass/cleanup_loop_offsets.hpp"
#include "snippets/lowered/pass/insert_tail_loop.hpp"
#include "snippets/lowered/pass/optimize_loop_single_evaluation.hpp"

#include "snippets/lowered/pass/pass_pipeline.hpp"
#include "snippets/op/kernel.hpp"

#include "snippets/itt.hpp"

namespace ov {
namespace snippets {

void Generator::generate(lowered::LinearIR& linear_ir, LoweringResult& result, const void* compile_params) const {
OV_ITT_SCOPED_TASK(ov::pass::itt::domains::SnippetsTransform, "Snippets::Generator::generate")
OV_ITT_TASK_CHAIN(GENERATE, ov::pass::itt::domains::SnippetsTransform, "Snippets::Generator", "::Transformations")
if (!target->is_supported())
OPENVINO_THROW("unsupported architecture for code generation");
OPENVINO_ASSERT(target->is_supported(), "unsupported architecture for code generation");

std::function<opRegType(const std::shared_ptr<Node>& op)> reg_type_mapper = [&](const std::shared_ptr<Node>& op) -> opRegType {
return get_op_reg_type(op);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
//

#include "snippets/lowered/pass/pass.hpp"
#include "snippets/lowered/pass/pass_pipeline.hpp"


namespace ov {
Expand All @@ -20,6 +20,16 @@ void PassPipeline::run(LinearIR& linear_ir) const {
}
}

void PassPipeline::register_positioned_passes(const std::vector<PositionedPass>& pos_passes) {
for (const auto& pp : pos_passes)
insert_pass_instance(pp.position, pp.pass);
}

void PassPipeline::insert_pass_instance(const ov::snippets::pass::PassPosition& position,
const std::shared_ptr<Pass>& pass) {
m_passes.insert(position.get_insert_position(m_passes), pass);
}

} // namespace pass
} // namespace lowered
} // namespace snippets
Expand Down
Loading

0 comments on commit b1165f9

Please sign in to comment.