| 492 | } |
| 493 | |
| 494 | cg::OperatorNodeBase* ExternCOprRunner::load( |
| 495 | OprLoadContext& ctx, const cg::VarNodeArray& inputs, |
| 496 | const OperatorNodeConfig& config) { |
| 497 | auto dump_name = ctx.load_buf_with_len(); |
| 498 | auto name = dump_name; |
| 499 | //! use to compat dump ExternCOprRunner with more info |
| 500 | if (auto index = name.find(":")) |
| 501 | name = name.substr(0, index); |
| 502 | auto&& map = loader_map(); |
| 503 | auto iter = map.find(name); |
| 504 | // !!For MegCC loader. |
| 505 | // If MegCC compiles a model containing an extern opr, it needs to use an extern |
| 506 | // opr loader. In order to make MegCC's compiler not dependent on the extern opr |
| 507 | // loader, MegCC registers a dummy loader with the name "extern_opr_dummy". |
| 508 | bool dummy_loader = false; |
| 509 | if (iter == map.end()) { |
| 510 | mgb_log_debug( |
| 511 | "Can NOT find loader '%s', try to find the dummy loader '%s'\n", |
| 512 | name.c_str(), DUMMY_LOADER_NAME); |
| 513 | iter = map.find(DUMMY_LOADER_NAME); |
| 514 | if (iter != map.end()) { |
| 515 | dummy_loader = true; |
| 516 | mgb_log_debug("Found the dummy extern opr loader.\n"); |
| 517 | } else { |
| 518 | mgb_log_debug("Can NOT find the dummy loader '%s'\n", DUMMY_LOADER_NAME); |
| 519 | } |
| 520 | } |
| 521 | mgb_assert( |
| 522 | iter != map.end(), "can not find loader for ExternCOprRunner '%s'", |
| 523 | name.c_str()); |
| 524 | auto data = ctx.load_shared_buf_with_len(); |
| 525 | MGBOprDesc* desc = nullptr; |
| 526 | |
| 527 | // For MegCC loader. |
| 528 | // If the loader is a MegCC dummy loader, copy the 'dump_name' in front of the |
| 529 | // 'data' to relate 'data' to 'name'. So multi loaders and multi extern oprs in |
| 530 | // single loader are supported. |
| 531 | if (dummy_loader) { |
| 532 | size_t buf_len = data.size() + sizeof(size_t) + dump_name.size(); |
| 533 | std::shared_ptr<void> buf{malloc(buf_len), free}; |
| 534 | char* buf_ptr = reinterpret_cast<char*>(buf.get()); |
| 535 | *(size_t*)buf_ptr = dump_name.size(); |
| 536 | buf_ptr += sizeof(size_t); |
| 537 | memmove(buf_ptr, dump_name.c_str(), dump_name.size()); |
| 538 | buf_ptr += dump_name.size(); |
| 539 | memmove(buf_ptr, data.data(), data.size()); |
| 540 | desc = iter->second.first.create_desc(inputs.size(), buf.get(), buf_len); |
| 541 | } else |
| 542 | desc = iter->second.first.create_desc(inputs.size(), data.data(), data.size()); |
| 543 | |
| 544 | mgb_throw_if(nullptr == desc, MegBrainError, "loader create desc returns nullptr"); |
| 545 | |
| 546 | if (auto trans = iter->second.second) { |
| 547 | desc = trans(desc); |
| 548 | } |
| 549 | |
| 550 | mgb_throw_if(nullptr == desc, MegBrainError, "loader create desc returns nullptr"); |
| 551 | |