| 1295 | } |
| 1296 | |
| 1297 | void Reduce::KernScheduler::execute( |
| 1298 | megdnn::Reduce* opr, const DeviceTensorND& input, const DeviceTensorND& dest) { |
| 1299 | if (m_apply_side_effect) { |
| 1300 | mgb_assert(m_kern_param.empty()); |
| 1301 | m_apply_side_effect(input, dest); |
| 1302 | return; |
| 1303 | } |
| 1304 | |
| 1305 | mgb_assert(!m_kern_param.empty()); |
| 1306 | |
| 1307 | // empty input |
| 1308 | if (input.shape_valid() && input.empty()) { |
| 1309 | auto mode = m_kern_param[0].kparam.mode; |
| 1310 | if (!m_fill_opr) { |
| 1311 | m_fill_opr = intl::get_megdnn_handle(dest.comp_node()) |
| 1312 | ->create_operator<megdnn::Fill>(); |
| 1313 | } |
| 1314 | |
| 1315 | if (dest.empty()) { |
| 1316 | return; |
| 1317 | } |
| 1318 | |
| 1319 | std::string err_msg; |
| 1320 | switch (mode) { |
| 1321 | case Reduce::Mode::SUM: |
| 1322 | if (!dest.empty()) { |
| 1323 | m_fill_opr->param() = 0; |
| 1324 | m_fill_opr->exec(dest.as_megdnn(), {}); |
| 1325 | } |
| 1326 | break; |
| 1327 | case Reduce::Mode::PRODUCT: |
| 1328 | if (!dest.empty()) { |
| 1329 | m_fill_opr->param() = 1; |
| 1330 | m_fill_opr->exec(dest.as_megdnn(), {}); |
| 1331 | } |
| 1332 | break; |
| 1333 | case Reduce::Mode::MEAN: |
| 1334 | if (!dest.empty()) { |
| 1335 | m_fill_opr->param() = {static_cast<float>(NAN)}; |
| 1336 | m_fill_opr->exec(dest.as_megdnn(), {}); |
| 1337 | } |
| 1338 | break; |
| 1339 | case Reduce::Mode::MIN: |
| 1340 | err_msg = "min"; |
| 1341 | break; |
| 1342 | case Reduce::Mode::MAX: |
| 1343 | err_msg = "max"; |
| 1344 | break; |
| 1345 | case Reduce::Mode::SUM_SQR: |
| 1346 | if (!dest.empty()) { |
| 1347 | m_fill_opr->param() = 0; |
| 1348 | m_fill_opr->exec(dest.as_megdnn(), {}); |
| 1349 | } |
| 1350 | break; |
| 1351 | default: |
| 1352 | mgb_throw(MegBrainError, "bad reduce mode"); |
| 1353 | } |
| 1354 | if (!err_msg.empty()) { |