Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Full documentation for MIGraphX is available at
* Added driver warnings when inputs dimensions and/or values are not set (#4850).
* Added documentation for using debug symbols (#4945).
* Added `--log-stdout` flag to migraphx-driver to log to stdout instead of stderr (#4959).
* Added logging of debug symbols on exception thrown (#4978).

### Changed

Expand Down
4 changes: 4 additions & 0 deletions src/include/migraphx/instruction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ struct MIGRAPHX_EXPORT instruction
std::size_t target_id = 0;
};

/// Logs the instruction's debug symbols (if any) to help trace a failure back to its source.
/// Intended to be invoked from a scope-fail guard during stack unwinding; never throws.
MIGRAPHX_EXPORT void log_debug_symbols_on_exception(const instruction& ins) noexcept;

} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx

Expand Down
64 changes: 64 additions & 0 deletions src/include/migraphx/scope_guard.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2026 Advanced Micro Devices, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MIGRAPHX_GUARD_MIGRAPHX_SCOPE_GUARD_HPP
#define MIGRAPHX_GUARD_MIGRAPHX_SCOPE_GUARD_HPP

#include <migraphx/config.hpp>
#include <exception>
#include <type_traits>
#include <utility>

namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {

// Runs the action only if the scope is exited via an exception.
template <class F>
struct scope_fail_guard
{
static_assert(std::is_nothrow_invocable<F&>{}, "scope_fail action must be noexcept");

F action;
int uncaught = std::uncaught_exceptions();

explicit scope_fail_guard(F f) : action(std::move(f)) {}

scope_fail_guard(const scope_fail_guard&) = delete;

~scope_fail_guard()
{
if(std::uncaught_exceptions() > uncaught)
action();
}
};

template <class F>
scope_fail_guard<F> on_scope_fail(F f)
{
return scope_fail_guard<F>{std::move(f)};
}

} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx

#endif // MIGRAPHX_GUARD_MIGRAPHX_SCOPE_GUARD_HPP
25 changes: 24 additions & 1 deletion src/instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <migraphx/ranges.hpp>
#include <migraphx/output_iterator.hpp>
#include <migraphx/iterator.hpp>
#include <migraphx/logger.hpp>
#include <migraphx/scope_guard.hpp>
#include <migraphx/stringutils.hpp>
#include <migraphx/iterator_for.hpp>
#include <migraphx/pmr/unordered_map.hpp>
Expand Down Expand Up @@ -99,6 +101,7 @@ void instruction::replace(const shape& r)
instruction_ref ins = q.top();
q.pop();
assert(ins->name() == "@return" or ins->name().front() != '@');
auto guard = on_scope_fail([&]() noexcept { log_debug_symbols_on_exception(*ins); });
Comment thread
eddieliao marked this conversation as resolved.
shape new_r = compute_shape(ins->op, ins->arguments, ins->module_args);
if(new_r != ins->result)
{
Expand All @@ -116,7 +119,11 @@ void instruction::replace(operation o)
recompute_shape();
}

void instruction::recompute_shape() { replace(compute_shape(op, arguments, module_args)); }
void instruction::recompute_shape()
{
auto guard = on_scope_fail([&]() noexcept { log_debug_symbols_on_exception(*this); });
Comment thread
eddieliao marked this conversation as resolved.
replace(compute_shape(op, arguments, module_args));
}

void instruction::clear_arguments()
{
Expand Down Expand Up @@ -632,6 +639,22 @@ std::vector<instruction_ref> get_added_instructions(const std::vector<instructio
return added;
}

void log_debug_symbols_on_exception(const instruction& ins) noexcept
{
try
{
const auto& symbols = ins.get_debug_symbols();
if(symbols.empty())
return;
log::debug() << "Exception thrown for instruction '" << ins.name()
<< "' with debug symbols: " << join_strings(symbols, ", ");
}
// cppcheck-suppress migraphx-EmptyCatchStatement
catch(...) // logging must not replace the original exception
{
}
}
Comment thread
Copilot marked this conversation as resolved.

migraphx::instruction* as_address(const std::list<instruction>::iterator& ins) noexcept
{
return iterator_address(ins);
Expand Down
8 changes: 7 additions & 1 deletion src/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <migraphx/shape.hpp>
#include <migraphx/stringutils.hpp>
#include <migraphx/instruction.hpp>
#include <migraphx/scope_guard.hpp>
#include <migraphx/target.hpp>
#include <migraphx/env.hpp>
#include <migraphx/ranges.hpp>
Expand Down Expand Up @@ -487,6 +488,7 @@ instruction_ref module::replace_instruction(instruction_ref ins,
impl->changed.notify();
assert(has_instruction(ins));
assert(not starts_with(op.name(), "@"));
auto guard = on_scope_fail([&]() noexcept { log_debug_symbols_on_exception(*ins); });
Comment thread
eddieliao marked this conversation as resolved.
auto out_shape = compute_shape(op, args, module_args);
std::vector<instruction_ref> prev_args;
if(has_debug_symbols())
Expand Down Expand Up @@ -572,6 +574,8 @@ module::batch_replace_instruction(const std::vector<instruction_replacement>& re
{
prev_args = replacer.ins->inputs();
}
auto guard =
on_scope_fail([&]() noexcept { log_debug_symbols_on_exception(*replacer.ins); });
Comment thread
eddieliao marked this conversation as resolved.
auto out_shape = compute_shape(replacer.op, replacer.args, replacer.module_args);
instruction::replace(
replacer.ins, replacer.op, out_shape, replacer.args, replacer.module_args);
Expand Down Expand Up @@ -844,7 +848,8 @@ instruction_ref module::replace_return(std::vector<instruction_ref> args)
return this->add_return(args);
}

shape r = compute_shape(last->get_operator(), args);
auto guard = on_scope_fail([&]() noexcept { log_debug_symbols_on_exception(*last); });
Comment thread
eddieliao marked this conversation as resolved.
shape r = compute_shape(last->get_operator(), args);
instruction::replace(last, last->get_operator(), r, std::move(args));
assert(last->valid(begin()));

Expand Down Expand Up @@ -1039,6 +1044,7 @@ std::vector<shape> module::compute_shapes(const std::vector<shape>& inputs,
[&](auto in) { return ins_shapes.at(in); });
if(ins->name() == "@return")
return input_shapes;
auto guard = on_scope_fail([&]() noexcept { log_debug_symbols_on_exception(*ins); });
Comment thread
eddieliao marked this conversation as resolved.
ins_shapes[ins] = ins->get_operator().compute_shape(input_shapes, ins->module_inputs());
}
}
Expand Down
35 changes: 31 additions & 4 deletions src/onnx/onnx_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <migraphx/make_op.hpp>
#include <migraphx/stringutils.hpp>
#include <migraphx/ranges.hpp>
#include <migraphx/scope_guard.hpp>
#include <migraphx/instruction.hpp>
#include <migraphx/common.hpp>
#include <migraphx/type_traits.hpp>
Expand Down Expand Up @@ -568,6 +569,31 @@ static void set_return_ins_debug_symbols(module* mod,
mod->add_debug_symbols(ret_ins, output_symbols);
}

static std::string make_node_debug_symbol(bool use_debug_symbols,
const onnx::NodeProto& node,
const std::string& node_name)
{
if(not use_debug_symbols)
return {};
return node.name().empty() ? "migx_uid:" + node_name : node.name();
}

static void log_node_parse_exception(const onnx::NodeProto& node,
const std::string& debug_symbol) noexcept
{
try
{
if(debug_symbol.empty())
return;
log::debug() << "Exception thrown while parsing node '" << node.op_type()
<< "' with debug symbols: " << debug_symbol;
}
// cppcheck-suppress migraphx-EmptyCatchStatement
catch(...) // logging must not replace the original exception
{
}
Comment thread
eddieliao marked this conversation as resolved.
}

std::vector<instruction_ref>
onnx_parser::parse_graph(module* mod, const onnx::GraphProto& graph, bool inlining)
{
Expand Down Expand Up @@ -619,8 +645,11 @@ onnx_parser::parse_graph(module* mod, const onnx::GraphProto& graph, bool inlini
}

std::vector<instruction_ref> result;
std::size_t output_num = node.output().size();
std::string node_name = node.op_type() + "_" + std::to_string(mod->size());
std::size_t output_num = node.output().size();
std::string node_name = node.op_type() + "_" + std::to_string(mod->size());
std::string debug_symbol = make_node_debug_symbol(this->use_debug_symbols, node, node_name);
auto guard =
on_scope_fail([&]() noexcept { log_node_parse_exception(node, debug_symbol); });
if(ops.count(node.op_type()) == 0)
{
if(skip_unknown_operators)
Expand All @@ -646,8 +675,6 @@ onnx_parser::parse_graph(module* mod, const onnx::GraphProto& graph, bool inlini
}
if(this->use_debug_symbols)
{
std::string debug_symbol =
node.name().empty() ? std::string("migx_uid:") + node_name : node.name();
for(auto ins : added_instructions)
{
mod->add_debug_symbols(ins, {debug_symbol});
Expand Down
2 changes: 2 additions & 0 deletions src/program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <migraphx/program.hpp>
#include <migraphx/stringutils.hpp>
#include <migraphx/instruction.hpp>
#include <migraphx/scope_guard.hpp>
#include <migraphx/op/identity.hpp>
#include <migraphx/target.hpp>
#include <migraphx/env.hpp>
Expand Down Expand Up @@ -501,6 +502,7 @@ static std::vector<argument> generic_eval(const module* mod,
results.emplace(ins, argument{});
#endif
const auto& name = ins->name();
auto guard = on_scope_fail([&]() noexcept { log_debug_symbols_on_exception(*ins); });
if(name == "@literal")
{
results.insert_or_assign(ins,
Expand Down
Loading