Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NPUW: Introduce 'last' keyword for dump options #26841

Merged
merged 5 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ static constexpr ov::Property<std::string> devices{"NPUW_DEVICES"};
* @brief
* Type: std::string.
* Force the specific subgraph to specific device. The device must be present in the NPUW_DEVICES list.
* Possible values: Comma-separated "Subgraph index:OpenVINO device name" pairs,
* e.g. "0:CPU,1:NPU".
* Possible values: Comma-separated "Subgraph index:OpenVINO device name" pairs, "last" keyword can be
* used for last subgraph, e.g. "0:CPU,1:NPU,last:CPU".
* Default value: empty.
*/
static constexpr ov::Property<std::string> submodel_device{"NPUW_SUBMODEL_DEVICE"};
Expand Down Expand Up @@ -323,7 +323,9 @@ static constexpr ov::Property<bool> full{"NPUW_DUMP_FULL"};
* Type: std::string.
* Dump the specified subgraph(s) in OpenVINO IR form in the current directory.
* Possible values: Comma-separated list of subgraph indices or "YES" for all
* subgraphs, "NO" or just empty value to turn option off. E.g. "0,1" or "YES".
* subgraphs, "NO" or just empty value to turn option off. Keyword "last" can
* be used for dumping last subgraph without specifying it by specific index.
* E.g. "0,1" or "0,1,last" or "YES".
* Default value: empty.
*/
static constexpr ov::Property<std::string> subgraphs{"NPUW_DUMP_SUBS"};
Expand All @@ -333,7 +335,8 @@ static constexpr ov::Property<std::string> subgraphs{"NPUW_DUMP_SUBS"};
* Type: std::string.
* Dump subgraph on disk if a compilation failure happens.
* Possible values: Comma-separated list of subgraph indices or "YES" for all
* subgraphs, "NO" or just empty value to turn option off. E.g. "0,1" or "YES".
* subgraphs, "NO" or just empty value to turn option off. Keyword "last" can
* be used for dumping last subgraph. E.g. "0,1" or "0,1,last" or "YES".
* Default value: empty.
*/
static constexpr ov::Property<std::string> subgraphs_on_fail{"NPUW_DUMP_SUBS_ON_FAIL"};
Expand All @@ -343,7 +346,8 @@ static constexpr ov::Property<std::string> subgraphs_on_fail{"NPUW_DUMP_SUBS_ON_
* Type: std::string.
* Dump input & output tensors for subgraph(s).
* Possible values: Comma-separated list of subgraph indices or "YES" for all
* subgraphs, "NO" or just empty value to turn option off. E.g. "0,1" or "YES".
* subgraphs, "NO" or just empty value to turn option off. Keyword "last" can
* be used for last subgraph. E.g. "0,1" or "0,1,last" or "YES".
* Default value: empty.
*/
static constexpr ov::Property<std::string> inputs_outputs{"NPUW_DUMP_IO"};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ void ov::npuw::IBaseInferRequest::infer() {

void ov::npuw::IBaseInferRequest::dump_input_tensors(std::size_t idx) {
const std::string dump_ios_opt = m_npuw_model->m_cfg.get<::intel_npu::NPUW_DUMP_IO>();
if (!ov::npuw::util::is_set(idx, dump_ios_opt)) {
const std::size_t end_idx = m_npuw_model->m_compiled_submodels.size();
if (!ov::npuw::util::is_set(idx, dump_ios_opt, end_idx)) {
return;
}

Expand Down Expand Up @@ -288,7 +289,8 @@ void ov::npuw::IBaseInferRequest::dump_input_tensors(std::size_t idx) {

void ov::npuw::IBaseInferRequest::dump_output_tensors(std::size_t idx) {
const std::string dump_ios_opt = m_npuw_model->m_cfg.get<::intel_npu::NPUW_DUMP_IO>();
if (!ov::npuw::util::is_set(idx, dump_ios_opt)) {
const std::size_t end_idx = m_npuw_model->m_compiled_submodels.size();
if (!ov::npuw::util::is_set(idx, dump_ios_opt, end_idx)) {
return;
}

Expand Down
16 changes: 13 additions & 3 deletions src/plugins/intel_npu/src/plugin/npuw/compiled_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <iostream>
#include <memory>
#include <string>

#include "accuracy/comparator.hpp"
#include "intel_npu/npu_private_properties.hpp"
Expand Down Expand Up @@ -256,6 +257,7 @@ ov::npuw::CompiledModel::CompiledModel(const std::shared_ptr<ov::Model>& model,
// - dump the subgraphs, if necessary
std::map<std::string, std::size_t> compiledFunctions;
m_compiled_submodels.resize(orderedSubgraphs.size());
const std::size_t end_sub_idx = orderedSubgraphs.size();

const std::string dump_sub_opt = m_cfg.get<::intel_npu::NPUW_DUMP_SUBS>();

Expand Down Expand Up @@ -323,7 +325,7 @@ ov::npuw::CompiledModel::CompiledModel(const std::shared_ptr<ov::Model>& model,
fill_empty_tensor_names(m_compiled_submodels[real_id].model);
}

if (ov::npuw::util::is_set(id, dump_sub_opt)) {
if (ov::npuw::util::is_set(id, dump_sub_opt, end_sub_idx)) {
LOG_INFO("Dumping Subgraph[" << id << "]");
LOG_BLOCK();
if (real_id != id) {
Expand All @@ -340,7 +342,14 @@ ov::npuw::CompiledModel::CompiledModel(const std::shared_ptr<ov::Model>& model,
} // for(orderedSubgraphs)

std::map<std::size_t, std::string> forced_sub_devices{};
const std::string fsd_opt = m_cfg.get<::intel_npu::NPUW_SUBMODEL_DEVICE>();
std::string fsd_opt = m_cfg.get<::intel_npu::NPUW_SUBMODEL_DEVICE>();
// Change "last" keyword to tail subgraph number
std::size_t last_pos = fsd_opt.find("last");
if (last_pos != std::string::npos) {
fsd_opt.erase(last_pos, 4);
fsd_opt.insert(last_pos, std::to_string(end_sub_idx));
}

forced_sub_devices = ::intel_npu ::OptionParser<std::map<std::size_t, std::string>>::parse(fsd_opt);

// Exclude optimized out subgraphs from compilation target beforehand - otherwise we might get head and repeated
Expand Down Expand Up @@ -694,8 +703,9 @@ ov::SoPtr<ov::ICompiledModel> ov::npuw::CompiledModel::compile_submodel(const st

void ov::npuw::CompiledModel::dump_on_fail(std::size_t id, const std::string& device_to_try, const char* extra) {
const std::string dof_opt = m_cfg.get<::intel_npu::NPUW_DUMP_SUBS_ON_FAIL>();
const std::size_t end_idx = m_compiled_submodels.size();

if (ov::npuw::util::is_set(id, dof_opt)) {
if (ov::npuw::util::is_set(id, dof_opt, end_idx)) {
ov::npuw::dump_failure(m_compiled_submodels[id].model, device_to_try, extra);
}
}
Expand Down
14 changes: 11 additions & 3 deletions src/plugins/intel_npu/src/plugin/npuw/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,28 @@
#include "openvino/runtime/make_tensor.hpp" // get_tensor_impl
#include "util_xarch.hpp"

bool ov::npuw::util::is_set(const std::size_t sub_idx, const std::string& opt) {
bool ov::npuw::util::is_set(const std::size_t sub_idx, const std::string& opt, const std::size_t end_idx) {
if (opt.empty() || opt == "NO") {
return false;
}
if (opt == "YES") {
return true;
}

std::string str(opt);
std::size_t last_pos = str.find("last");
if (last_pos != std::string::npos) {
str.erase(last_pos, 4);
if (end_idx != SIZE_MAX && sub_idx == end_idx - 1) {
return true;
}
}

std::vector<std::size_t> sub_inds{};
sub_inds = ::intel_npu ::OptionParser<std::vector<std::size_t>>::parse(opt);
sub_inds = ::intel_npu ::OptionParser<std::vector<std::size_t>>::parse(str);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to cover ::parse() handle this case - it will be one place for all

if (std::find(sub_inds.begin(), sub_inds.end(), sub_idx) != sub_inds.end()) {
return true;
}

return false;
}

Expand Down
2 changes: 1 addition & 1 deletion src/plugins/intel_npu/src/plugin/npuw/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace ov {
namespace npuw {
namespace util {

bool is_set(const std::size_t sub_idx, const std::string& opt);
bool is_set(const std::size_t sub_idx, const std::string& opt, const std::size_t end_idx = SIZE_MAX);

// Every great project has its own string class...
// NB: Newer C++ standards would allow to use string views or smt
Expand Down
Loading