feat: parallelize multimodal decode in request transfer.#1474
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors the multi-modal input processing logic to enable parallel decoding. The MMHandlerSet::process method is split into load and decode phases, and MMInputTransfer now utilizes a ThreadPool and BlockingCounter to execute decoding tasks concurrently. Feedback focuses on adhering to the repository style guide, specifically regarding project-root-relative include paths, annotating constant arguments, reserving vector capacity, using early continue in loops to reduce nesting, and applying static_cast for type conversions.
| #include "util/blocking_counter.h" | ||
| #include "util/threadpool.h" |
There was a problem hiding this comment.
According to the repository style guide, all includes must use project-root-relative paths. The current paths are missing the core/ prefix.
| #include "util/blocking_counter.h" | |
| #include "util/threadpool.h" | |
| #include "core/util/blocking_counter.h" | |
| #include "core/util/threadpool.h" |
References
- No relative paths in #include. Always use project-root-relative paths. (link)
|
|
||
| MMInputTransfer::MMInputTransfer() { | ||
| mm_handlers_ = std::make_unique<MMHandlerSet>(); | ||
| threadpool_ = std::make_unique<ThreadPool>(16); |
There was a problem hiding this comment.
Constant arguments in constructor calls should be annotated with the parameter name to improve readability, as per the repository style guide.
| threadpool_ = std::make_unique<ThreadPool>(16); | |
| threadpool_ = std::make_unique<ThreadPool>(/*num_threads=*/16); |
References
- Annotate constant arguments with a comment indicating the parameter name when calling functions or constructors. (link)
| @@ -50,22 +61,69 @@ MMErrCode MMInputTransfer::trans(const MMContentVec& mmc, | |||
| std::vector<MMInputItem>& inputs, | |||
| MMPayload& payload) { | |||
| inputs.clear(); | |||
There was a problem hiding this comment.
The repository style guide requires calling reserve() before filling a std::vector when the size is known or can be estimated. Since mmc.size() is known, we should reserve capacity for inputs.
| inputs.clear(); | |
| inputs.clear(); | |
| inputs.reserve(mmc.size()); |
References
- Always reserve() before filling a std::vector when the size is known or can be estimated. (link)
| if (type != "text") { | ||
| MMInputItem input; | ||
| MMErrCode code = mm_handlers_->process(type, item, input, payload); | ||
| MMErrCode code = mm_handlers_->load(type, item, input, payload); | ||
| if (code != MMErrCode::SUCCESS) { | ||
| return code; | ||
| } | ||
|
|
||
| inputs.emplace_back(std::move(input)); | ||
| decode_tasks.emplace_back(DecodeTask{ | ||
| .type = type, | ||
| .input_index = inputs.size() - 1, | ||
| }); | ||
| } |
There was a problem hiding this comment.
The repository style guide recommends avoiding if blocks inside for loops for filtering logic. Using an early continue reduces indentation and improves readability.
if (type == "text") {
continue;
}
MMInputItem input;
MMErrCode code = mm_handlers_->load(type, item, input, payload);
if (code != MMErrCode::SUCCESS) {
return code;
}
inputs.emplace_back(std::move(input));
decode_tasks.emplace_back(DecodeTask{
.type = type,
.input_index = inputs.size() - 1,
});References
- Avoid if inside for loops when possible. Prefer filtering the data beforehand or restructuring the logic (e.g., early continue). (link)
| return MMErrCode::SUCCESS; | ||
| } | ||
|
|
||
| BlockingCounter counter(decode_tasks.size()); |
There was a problem hiding this comment.
The repository style guide requires using static_cast for all type conversions. Converting size_t to int32_t (as required by the BlockingCounter constructor) should be explicit.
| BlockingCounter counter(decode_tasks.size()); | |
| BlockingCounter counter(static_cast<int32_t>(decode_tasks.size())); |
References
- Use static_cast for all type conversions. Never use C-style casts. (link)
No description provided.