跳至主要内容

執行緒模型

一個正在執行的 Run 會在框架和執行階段執行緒上執行工作。您的應用程式不需要管理這些執行緒,但它需要確保其自身的推送、拉取、回調和關閉程式碼保持良好狀態。

執行緒統計

對於典型的 Run

執行緒角色所屬者
GStreamer 串流執行緒將緩衝區移動到來源、轉換和接收路徑中。GStreamer 執行階段
MLA 派遣執行緒提交 MLA 工作並處理完成結果。Neat 執行階段
EV74 / CVU 派遣執行緒提交 CVU 端核心並輪詢完成狀態。Neat 執行階段
拉取端等待者和匯流排監視器將輸出樣本移動到公共佇列中,並報告執行階段錯誤。Neat 執行階段
應用程式執行緒呼叫 Graph.build(...)Graph.run(...)Run.push(...)Run.pull(...)Run.stop() 或回調。您的應用程式

Graph 片段、來源節點和接收節點可以新增執行階段工作,但規則不變:公開的 Run 是由應用程式控制的句柄。

應用程式程式碼的執行位置

使用者程式碼出現在以下位置:

  • 直接 API 呼叫build(...)run(...)push(...)try_push(...)pull(...)close_input()stop()close() 在呼叫它們的應用程式執行緒上執行。
  • 關閉回調RunOptions.on_input_drop 在推送路徑上執行。保持簡短;計算並傳回。
  • 張量回調Graph::set_tensor_callback(...) 是一種 C++ 回調樣式的消耗方式。保持回調簡短,因為長時間的工作會對執行階段路徑產生反壓。
  • 自訂節點描述:公共節點建構和圖組成在建構時發生,在應用程式執行緒上。

不要將耗時的操作隱藏在回調中。如果回調需要執行大量工作,請將樣本傳遞到您自己的佇列中,然後傳回。

鎖定規則

除非 API 另有說明,否則將 GraphRunTensorSample 視為單一所有者物件。

支援的模式:

  • 一個生產者執行緒呼叫 push(...)try_push(...)
  • 一個消費者執行緒呼叫 pull(...)
  • 另一個協調執行緒可以在關閉時呼叫 stop()

有風險的模式:

  • 幾個生產者執行緒推送到同一個 Run,而沒有鎖定;
  • 幾個消費者執行緒從同一個輸出拉取,而沒有明確的擁有權規則;
  • 一個回調呼叫到同一個 Run,並等待更多工作。

如果您需要多個生產者,請在呼叫 Run.push(...) 之前序列化訪問。如果您需要多個消費者,請在一個執行緒從 Neat 拉取後進行分流。

關閉和取消

使用與意圖匹配的關閉原語:

意圖使用
在最後一個輸入之後完成佇列中的工作run.close_input(),然後拉取,直到沒有更多輸出或傳回 PullStatus::Closed
現在停止並解除阻塞等待中的工作run.stop()
釋放執行階段資源run.close() 或讓 Run 物件離開作用域

stop() 是取消路徑。取消後,正在進行中的讀取操作將會解除阻塞,並且推送操作應該停止。不要繼續將資料推送至即將結束的執行階段。

吞吐量執行緒模型

對於應用程式推送的即時或高吞吐量圖,從兩個應用程式執行緒開始:

  1. 一個生產者執行緒讀取輸入,加上 stream_id / frame_id,並根據選定的 OverflowPolicy 呼叫 try_push(...)push(...)
  2. 一個消費者執行緒持續讀取,並在資料被固定到由執行階段支援的緩衝區之前釋放或複製輸出。

在您自己的佇列周圍新增更多應用程式執行緒,而不是在同一個 Run 物件周圍新增。讓熱迴圈變得單調。單調意味著快速。

更多閱讀