/** * \file src/plugin/impl/cpu_dispatch_checker.cpp * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") * * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ #include "megbrain/plugin/cpu_dispatch_checker.h" #include "megbrain/comp_node_env.h" #include "megbrain/graph.h" #include "megbrain/graph/event.h" using namespace mgb; CPUDispatchChecker::CPUDispatchChecker(cg::ComputingGraph* graph) : PluginBase(graph) { auto on_exec_start = [this](const cg::event::OprExecKernelStart& event) { for (auto cn : cg::get_opr_comp_node_set(event.opr)) { if (cn.device_type() == CompNode::DeviceType::CPU) { auto callback = [this, cn]() { record(cn); }; event.env->dispatch_on_comp_node(cn, callback); } } }; auto on_exec_finish = [this](const cg::event::OprExecKernelEnd& event) { for (auto cn : cg::get_opr_comp_node_set(event.opr)) { if (cn.device_type() == CompNode::DeviceType::CPU) { auto callback = [this, cn, opr = event.opr]() { check(cn, opr); }; event.env->dispatch_on_comp_node(cn, callback); } } }; auto on_subgraph_associated = [this](const cg::event::SubgraphAssociated& event) { mgb_assert(event.par_graph == m_owner_graph); auto sub = std::make_unique(event.sub_graph); sub->m_failed_oprs = m_failed_oprs; sub->m_failed_oprs_mtx = m_failed_oprs_mtx; m_sub_graph_checkers.emplace_back(std::move(sub)); }; add_event_handler(graph->event().register_receiver( on_exec_start)); add_event_handler(graph->event().register_receiver( on_exec_finish)); add_event_handler(graph->event().register_receiver( on_subgraph_associated)); } void CPUDispatchChecker::record(CompNode cn) { auto num = CompNodeEnv::from_comp_node(cn) .cpu_env() .dispatcher->get_nr_dispatched_tasks(); MGB_LOCK_GUARD(m_cn2nr_task_mtx); m_cn2nr_task[cn] = num; } void CPUDispatchChecker::check(CompNode cn, cg::OperatorNodeBase* opr) { size_t prev, now; { MGB_LOCK_GUARD(m_cn2nr_task_mtx); prev = m_cn2nr_task.at(cn); } now = CompNodeEnv::from_comp_node(cn) .cpu_env() .dispatcher->get_nr_dispatched_tasks(); if (prev == now) { fprintf(stderr, "operator %s{%s} does not dispatch kernel on %s\n", opr->cname(), opr->dyn_typeinfo()->name, cn.to_string().c_str()); { MGB_LOCK_GUARD(*m_failed_oprs_mtx); m_failed_oprs->insert(opr); } } } // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}