================== ProfilerImpl =================*/
| 121 | |
| 122 | /* ================== ProfilerImpl =================*/ |
| 123 | ProfilerImpl::ProfilerImpl(int runs, float opr_threshold, float var_node_threshold) |
| 124 | : m_opr_threshold{opr_threshold}, |
| 125 | m_var_node_threshold{var_node_threshold}, |
| 126 | m_runs{runs} { |
| 127 | m_opr_filter = [this](const OperatorNodeBase* opr, OperatorNodeBase* new_opr) { |
| 128 | /// \note: for the considerations of performance, we skip nchw(naive) |
| 129 | /// kernels for conv bias on CUDA platform. to remove this later |
| 130 | if (auto conv = try_cast_as_op<opr::ConvBiasForward>(new_opr)) { |
| 131 | if (conv->output(0)->comp_node().device_type() == |
| 132 | CompNode::DeviceType::CUDA && |
| 133 | conv->input(0)->dtype().category() == DTypeCategory::QUANTIZED && |
| 134 | conv->param().format == OprFormat::NCHW) { |
| 135 | return false; |
| 136 | } |
| 137 | } |
| 138 | float comp1 = |
| 139 | m_opr_footprint.get_computation(const_cast<OperatorNodeBase*>(opr)); |
| 140 | float comp2 = m_opr_footprint.get_computation(new_opr); |
| 141 | if (comp2 > m_opr_threshold * comp1) |
| 142 | return false; |
| 143 | return true; |
| 144 | }; |
| 145 | m_var_node_filter = [this](const VarNode* var, TensorShape from, TensorShape to, |
| 146 | ReformatKey key) { |
| 147 | /// \note: due to the alignment requirement of low-bit tensor, we skip |
| 148 | /// some layout transform for low-bit tensors. The skipped layout |
| 149 | /// transforms do not have corresponding dnn kernel and cannot be |
| 150 | /// implemented by tensor manip operators (like reshape, dimshuffle, |
| 151 | /// subtensor, etc.). |
| 152 | if (var->dtype().enumv() == DTypeEnum::QuantizedS4 || |
| 153 | var->dtype().enumv() == DTypeEnum::Quantized4Asymm) { |
| 154 | if (key.input_format == TensorFormats::NCHW && |
| 155 | key.output_format != TensorFormats::NHWC && |
| 156 | key.output_format != TensorFormats::NCHWc64) { |
| 157 | return false; |
| 158 | } |
| 159 | if (key.output_format == TensorFormats::NCHW && |
| 160 | key.input_format != TensorFormats::NHWC && |
| 161 | key.input_format != TensorFormats::NCHWc64) { |
| 162 | return false; |
| 163 | } |
| 164 | } |
| 165 | TensorLayout orig_ly = {var->shape(), var->dtype()}, |
| 166 | from_ly = {from, var->dtype()}, to_ly = {to, var->dtype()}; |
| 167 | float orig_memory = orig_ly.span().dist_byte() * 2.f; |
| 168 | float reformat_memory = from_ly.span().dist_byte() + to_ly.span().dist_byte(); |
| 169 | if (reformat_memory > orig_memory * m_var_node_threshold) |
| 170 | return false; |
| 171 | return true; |
| 172 | }; |
| 173 | } |
| 174 | |
| 175 | ProfilerImpl::OperatorNodeRecord ProfilerImpl::profile_operator( |
| 176 | const OperatorNodeBase* opr, TensorFormats base_format, |
nothing calls this directly
no test coverage detected