Skip to content

feat: 增加MaaContextRunRecognitionList并行识别#1348

Closed
zmdyy0318 wants to merge 2 commits into
MaaXYZ:mainfrom
zmdyy0318:feat/2026053001
Closed

feat: 增加MaaContextRunRecognitionList并行识别#1348
zmdyy0318 wants to merge 2 commits into
MaaXYZ:mainfrom
zmdyy0318:feat/2026053001

Conversation

@zmdyy0318
Copy link
Copy Markdown
Contributor

@zmdyy0318 zmdyy0318 commented May 30, 2026

背景:maaend实时任务用,ipc只能串行执行,因此加一个RecognitionList方法,全部识别完成后返回结果。

内部实现:
普通节点并行识别,custom节点串行执行

返回值:博爱成功或失败
输出:MaaRecoId* 识别结果数组,长度根据传入entries_json 个数决定

MAA_FRAMEWORK_API MaaBool MaaContextRunRecognitionList(
        MaaContext* context,
        const char* entries_json,
        const char* pipeline_override,
        const MaaImageBuffer* image,
        /* out */ MaaRecoId* reco_ids);

opus4.8

Summary by Sourcery

添加了一个新的 API 和 IPC 路径,用于在单帧图像上并行运行针对多个条目的识别,并返回首个命中的索引;同时使模型/模板资源管理器在并发识别场景下实现线程安全。

New Features:

  • 引入 Context::run_recognition_list 以及对应的 C API MaaContextRunRecognitionList,用于在同一张图像上识别多个条目,并返回优先级最高的命中索引。
  • 增加远程/agent 消息类型和处理程序,以在 MaaAgent IPC 协议上支持 context run-recognition-list,并更新协议版本。
  • 从 MaaFramework 模块接口中重新导出 MaaContextRunRecognitionList

Enhancements:

  • 将对多个条目的识别拆分为并行的本地识别和串行的 Custom 识别,以避免 IPC 争用,同时保持优先级语义。
  • 通过使用互斥锁保护惰性加载的模型和图像缓存,使 OCR、ONNX 和模板资源管理器线程安全,从而支持安全的并发识别。

Documentation:

  • 在公共头文件中记录 MaaContextRunRecognitionList API 的行为、参数和返回值。
Original summary in English

Summary by Sourcery

Add a new API and IPC path to run recognition on a list of entries against a single frame in parallel, returning the first hit index, and make model/template resource managers thread-safe for concurrent recognition.

New Features:

  • Introduce Context::run_recognition_list and corresponding MaaContextRunRecognitionList C API to recognize multiple entries on the same image and return the highest-priority hit index.
  • Add remote/agent message types and handlers to support context run-recognition-list over the MaaAgent IPC protocol, updating the protocol version.
  • Re-export MaaContextRunRecognitionList from the MaaFramework module interface.

Enhancements:

  • Split recognition of multiple entries into parallel local recognitions and serialized Custom recognitions to avoid IPC contention while preserving priority semantics.
  • Make OCR, ONNX, and template resource managers thread-safe by guarding lazy-loaded model and image caches with mutexes, enabling safe concurrent recognition.

Documentation:

  • Document the MaaContextRunRecognitionList API behavior, parameters, and return value in the public header.

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 1 个问题,并给出了一些整体性的反馈:

  • TemplateResMgr::get_image 中,互斥锁在整个惰性加载流程中都被持有,包括 cv::imread,这可能会引入不必要的锁竞争;建议拆分临界区,使映射查找/更新在锁保护下进行,而潜在耗时的磁盘 I/O 则在锁外完成。
  • 对于 OCRResMgr::clearONNXResMgr::clear,你现在只用 models_mutex_ 保护模型 map,而没有保护 roots_;如果识别线程中也会访问 roots_,建议在访问 roots_ 时也持有同一把互斥锁,以保持一致并避免潜在的数据竞争。
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `TemplateResMgr::get_image`, the mutex is held across the entire lazy-load path including `cv::imread`, which may introduce unnecessary contention; consider splitting the critical section so that the map lookup/update is protected but the potentially expensive disk I/O happens outside the lock.
- For `OCRResMgr::clear` and `ONNXResMgr::clear`, you now protect only the model maps with `models_mutex_` but not `roots_`; if `roots_` is also accessed from recognition threads, you may want to hold the same mutex while touching it for consistency and to avoid potential data races.

## Individual Comments

### Comment 1
<location path="source/MaaFramework/Resource/OCRResMgr.cpp" line_range="97-101" />
<code_context>
     LogFunc;

     roots_.clear();
+    std::lock_guard lock(models_mutex_);
     deters_.clear();
     recers_.clear();
     ocrers_.clear();
</code_context>
<issue_to_address>
**issue (bug_risk):** `clear()` only guards model maps, not `roots_`, which can still race with concurrent access.

`roots_.clear()` runs without `models_mutex_`, while `deters_/recers_/ocrers_` are cleared under that lock. If any code holds `models_mutex_` and reads `roots_` (e.g., in lazy-load paths for deter/recer/ocrer), this creates a data race on `roots_`. Please either clear `roots_` under `models_mutex_` as well, or guarantee that `roots_` is only ever modified in a single-threaded context and never accessed concurrently with `clear()`.
</issue_to_address>

Sourcery 对开源项目是免费的——如果你觉得我们的代码审查有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的代码审查。
Original comment in English

Hey - I've found 1 issue, and left some high level feedback:

  • In TemplateResMgr::get_image, the mutex is held across the entire lazy-load path including cv::imread, which may introduce unnecessary contention; consider splitting the critical section so that the map lookup/update is protected but the potentially expensive disk I/O happens outside the lock.
  • For OCRResMgr::clear and ONNXResMgr::clear, you now protect only the model maps with models_mutex_ but not roots_; if roots_ is also accessed from recognition threads, you may want to hold the same mutex while touching it for consistency and to avoid potential data races.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `TemplateResMgr::get_image`, the mutex is held across the entire lazy-load path including `cv::imread`, which may introduce unnecessary contention; consider splitting the critical section so that the map lookup/update is protected but the potentially expensive disk I/O happens outside the lock.
- For `OCRResMgr::clear` and `ONNXResMgr::clear`, you now protect only the model maps with `models_mutex_` but not `roots_`; if `roots_` is also accessed from recognition threads, you may want to hold the same mutex while touching it for consistency and to avoid potential data races.

## Individual Comments

### Comment 1
<location path="source/MaaFramework/Resource/OCRResMgr.cpp" line_range="97-101" />
<code_context>
     LogFunc;

     roots_.clear();
+    std::lock_guard lock(models_mutex_);
     deters_.clear();
     recers_.clear();
     ocrers_.clear();
</code_context>
<issue_to_address>
**issue (bug_risk):** `clear()` only guards model maps, not `roots_`, which can still race with concurrent access.

`roots_.clear()` runs without `models_mutex_`, while `deters_/recers_/ocrers_` are cleared under that lock. If any code holds `models_mutex_` and reads `roots_` (e.g., in lazy-load paths for deter/recer/ocrer), this creates a data race on `roots_`. Please either clear `roots_` under `models_mutex_` as well, or guarantee that `roots_` is only ever modified in a single-threaded context and never accessed concurrently with `clear()`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 97 to 101
roots_.clear();
std::lock_guard lock(models_mutex_);
deters_.clear();
recers_.clear();
ocrers_.clear();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): clear() 只对模型 map 加锁保护,而没有保护 roots_,这仍然可能与并发访问产生竞争。

roots_.clear() 在没有持有 models_mutex_ 的情况下执行,而 deters_/recers_/ocrers_ 是在这把锁下被清理的。如果有任何代码在持有 models_mutex_ 的同时读取 roots_(例如在 deter/recer/ocrer 的惰性加载路径中),就会在 roots_ 上产生数据竞争。请要么也在持有 models_mutex_ 的情况下清理 roots_,要么保证 roots_ 只会在单线程上下文中被修改,并且不会在与 clear() 并发的情况下被访问。

Original comment in English

issue (bug_risk): clear() only guards model maps, not roots_, which can still race with concurrent access.

roots_.clear() runs without models_mutex_, while deters_/recers_/ocrers_ are cleared under that lock. If any code holds models_mutex_ and reads roots_ (e.g., in lazy-load paths for deter/recer/ocrer), this creates a data race on roots_. Please either clear roots_ under models_mutex_ as well, or guarantee that roots_ is only ever modified in a single-threaded context and never accessed concurrently with clear().

@MistEO
Copy link
Copy Markdown
Member

MistEO commented May 30, 2026

好丑啊,不太行。

最好想个法子从 pipeline 的角度支持

@zmdyy0318
Copy link
Copy Markdown
Contributor Author

好丑啊,不太行。

最好想个法子从 pipeline 的角度支持

ok

@zmdyy0318 zmdyy0318 closed this May 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants