Triton Server部署Embedding模型

在32核CPU、無GPU的服務器上,使用Python后端和ONNX后端部署嵌入模型,并實現并行調用和性能優化策略。


方案一:使用Python后端部署Embedding模型

Python后端提供了極大的靈活性,可以直接在Triton中運行您熟悉的sentence-transformers代碼。但其性能開銷相對較高,需要精細配置以充分利用CPU資源。

1. 拉取Triton Docker鏡像

首先,拉取包含Python后端的Triton Server官方鏡像。

# 將<xx.yy>替換為最新或您需要的版本,例如 24.06
docker pull nvcr.io/nvidia/tritonserver:<xx.yy>-py3
2. 準備模型倉庫

您需要創建一個模型目錄,其中包含一個model.py腳本(用于加載和運行模型)和一個config.pbtxt配置文件(用于定義模型行為和優化)。

  1. 創建目錄結構

    mkdir -p model_repository/embedding_py/1
    
  2. 創建model.py腳本
    此腳本的核心是在initialize方法中加載模型(只執行一次),并在execute方法中處理推理請求。

    # 保存為 model_repository/embedding_py/1/model.py
    import json
    import numpy as np
    import torch
    from sentence_transformers import SentenceTransformer
    import triton_python_backend_utils as pb_utilsclass TritonPythonModel:def initialize(self, args):"""在模型加載時調用一次。"""# 關鍵性能優化:當Triton實例數(count) > 1時,限制每個實例的PyTorch線程數# 可以避免實例間的線程競爭,讓Triton來調度并行。torch.set_num_threads(1)# 從模型目錄加載模型,使用CPUself.model = SentenceTransformer(args['model_repository'], device='cpu')print('SentenceTransformer model loaded on CPU.')def execute(self, requests):"""處理每一批推理請求。"""responses =for request in requests:# 1. 從請求中獲取輸入張量 (文本字符串)# as_numpy()會返回一個包含字節串的NumPy數組in_str = pb_utils.get_input_tensor_by_name(request, "TEXT")sentences = [s.decode('utf-8') for s in in_str.as_numpy()]# 2. 使用模型進行推理embeddings = self.model.encode(sentences, convert_to_numpy=True)# 3. 創建輸出張量out_tensor = pb_utils.Tensor("EMBEDDING", embeddings.astype(np.float32))# 4. 創建并添加響應inference_response = pb_utils.InferenceResponse(output_tensors=[out_tensor])responses.append(inference_response)return responsesdef finalize(self):"""在模型卸載時調用。"""self.model = Noneprint('Cleaned up model.')
    
  3. 創建config.pbtxt配置文件
    這是CPU性能優化的關鍵。我們將創建多個模型實例(instance_group)以利用全部32個核心。

    # 保存為 model_repository/embedding_py/config.pbtxt
    name: "embedding_py"
    backend: "python"
    max_batch_size: 64 # 允許服務器對請求進行批處理input # 可變長度的字符串輸入}
    ]output # 假設嵌入維度為768}
    ]# --- 性能優化配置 ---
    # 為CPU創建多個模型實例以實現并行處理
    instance_group# 動態批處理:在CPU上依然有用,可以分攤請求開銷
    dynamic_batching {max_queue_delay_microseconds: 10000 # 10毫秒延遲換取更大批次preferred_batch_size: 
    }
    
3. 啟動Triton服務器 (CPU模式)

使用docker run命令啟動服務器,注意不使用--gpus標志。

docker run --rm -p 8000:8000 -p 8001:8001 -p 8002:8002 \
-v $(pwd)/model_repository:/models \
nvcr.io/nvidia/tritonserver:<xx.yy>-py3 \
tritonserver --model-repository=/models

服務器啟動后,您會看到日志顯示embedding_py模型已經READY

4. 并行推理客戶端

為了充分利用服務器端配置的16個實例,客戶端必須能夠并行地發送請求。使用asyncioaiohttp是實現高并發客戶端的有效方式。

# client_py.py
import asyncio
import numpy as np
import tritonclient.http.aio as aiohttpclientSERVER_URL = "localhost:8000"
MODEL_NAME = "embedding_py"async def send_request(client, text_list):# 準備輸入數據text_array = np.array([[s.encode('utf-8')] for s in text_list], dtype=np.object_)inputs =inputs.set_data_from_numpy(text_array, binary_data=True)# 準備輸出outputs =# 發送請求response = await client.infer(MODEL_NAME, inputs, outputs=outputs)embedding = response.as_numpy("EMBEDDING")return embeddingasync def main():# 模擬大量并發任務tasks =# 創建一個可以并行發送請求的客戶端async with aiohttpclient.InferenceServerClient(SERVER_URL) as client:# 假設我們要并行處理100個請求,每個請求包含4個句子for i in range(100):task_texts =tasks.append(send_request(client, task_texts))# 等待所有并發請求完成results = await asyncio.gather(*tasks)print(f"成功完成 {len(results)} 個并行任務。")print(f"第一個任務的嵌入向量形狀: {results.shape}")if __name__ == "__main__":asyncio.run(main())
5. Python后端性能優化策略總結
  • 核心策略:增加實例數 (instance_group):這是在多核CPU上實現吞吐量擴展的最重要手段。將count設置為接近CPU核心數(例如16, 24, 32),讓Triton的多個模型實例并行處理請求。
  • 限制實例內線程 (torch.set_num_threads(1)):當count > 1時,這是至關重要的優化。它避免了多個PyTorch實例爭搶CPU資源,將并行化的任務完全交給Triton調度,從而減少了線程切換的開銷。
  • 動態批處理 (dynamic_batching):雖然在CPU上的收益不如GPU明顯,但它仍然可以通過將小請求聚合成大批次,來分攤Python解釋器和請求處理的固定開銷,從而提升吞吐量。

方案二:使用ONNX后端部署Embedding模型

ONNX (Open Neural Network Exchange) 是一種為機器學習模型設計的開放格式。使用ONNX后端通常比Python后端性能更高,因為它繞過了Python解釋器,直接由高度優化的C++運行時(ONNX Runtime)執行。

1. 轉換模型為ONNX格式

首先,您需要將sentence-transformers模型導出為ONNX格式。使用optimum庫是最簡單的方式。

pip install optimum[exporters]
# 將 BAAI/bge-base-en-v1.5 替換為您想使用的模型
optimum-cli export onnx --model BAAI/bge-base-en-v1.5 --task feature-extraction./embedding_onnx_model

執行后,./embedding_onnx_model目錄下會生成model.onnx文件。

2. 準備模型倉庫
  1. 創建目錄結構并移動模型

    mkdir -p model_repository/embedding_onnx/1
    mv./embedding_onnx_model/model.onnx model_repository/embedding_onnx/1/
    
  2. 創建config.pbtxt配置文件
    此配置將指向ONNX模型,并同樣通過instance_group進行CPU優化。

    # 保存為 model_repository/embedding_onnx/config.pbtxt
    name: "embedding_onnx"
    backend: "onnxruntime" # 或 platform: "onnxruntime_onnx"
    max_batch_size: 128input # 動態批處理, 動態序列長度},{name: "attention_mask"data_type: TYPE_INT64dims: [ -1, -1 ]}
    ]output # 假設嵌入維度為768}
    ]# --- 性能優化配置 ---
    instance_groupdynamic_batching {max_queue_delay_microseconds: 5000 # 5毫秒延遲preferred_batch_size: 
    }
    
3. 啟動Triton服務器 (CPU模式)

啟動命令與Python后端完全相同,Triton會自動發現并加載embedding_onnx模型。

docker run --rm -p 8000:8000 -p 8001:8001 -p 8002:8002 \
-v $(pwd)/model_repository:/models \
nvcr.io/nvidia/tritonserver:<xx.yy>-py3 \
tritonserver --model-repository=/models
4. 并行推理客戶端

ONNX模型的客戶端需要一個額外的步驟:文本分詞(Tokenization)。這個過程需要在客戶端完成,因為預處理邏輯沒有像Python后端那樣被部署在服務器上。

# client_onnx.py
import asyncio
import numpy as np
import tritonclient.http.aio as aiohttpclient
from transformers import AutoTokenizerSERVER_URL = "localhost:8000"
MODEL_NAME = "embedding_onnx"
# 使用與導出ONNX時相同的模型名稱來加載分詞器
TOKENIZER_NAME = "BAAI/bge-base-en-v1.5" # 在全局加載分詞器
tokenizer = AutoTokenizer.from_pretrained(TOKENIZER_NAME)def mean_pooling(model_output, attention_mask):# 從ONNX輸出中提取嵌入向量token_embeddings = model_outputinput_mask_expanded = np.expand_dims(attention_mask, -1).repeat(token_embeddings.shape[-1], -1)sum_embeddings = np.sum(token_embeddings * input_mask_expanded, 1)sum_mask = np.clip(input_mask_expanded.sum(1), a_min=1e-9, a_max=None)return sum_embeddings / sum_maskasync def send_request(client, text_list):# 1. 客戶端分詞encoded_input = tokenizer(text_list, padding=True, truncation=True, return_tensors='np')# 2. 準備輸入張量inputs = [aiohttpclient.InferInput("input_ids", encoded_input['input_ids'].shape, "INT64"),aiohttpclient.InferInput("attention_mask", encoded_input['attention_mask'].shape, "INT64")]inputs.set_data_from_numpy(encoded_input['input_ids'])inputs.[1]set_data_from_numpy(encoded_input['attention_mask'])# 3. 準備輸出outputs =# 4. 發送請求response = await client.infer(MODEL_NAME, inputs, outputs=outputs)last_hidden_state = response.as_numpy("last_hidden_state")# 5. 客戶端后處理 (Mean Pooling)final_embedding = mean_pooling(last_hidden_state, encoded_input['attention_mask'])return final_embeddingasync def main():# 并發邏輯與Python后端客戶端相同tasks =async with aiohttpclient.InferenceServerClient(SERVER_URL) as client:for i in range(100):task_texts =tasks.append(send_request(client, task_texts))results = await asyncio.gather(*tasks)print(f"成功完成 {len(results)} 個并行任務。")print(f"第一個任務的嵌入向量形狀: {results.shape}")if __name__ == "__main__":asyncio.run(main())
5. ONNX后端性能優化策略總結
  • 核心策略:增加實例數 (instance_group):與Python后端同理,這是利用多核CPU的關鍵。
  • 模型優化:ONNX的優勢在于其生態系統。在部署前,您可以使用ONNX Runtime工具對模型進行圖優化量化(Quantization)。將模型從FP32量化為INT8,可以在CPU上帶來數倍的性能提升,同時只有輕微的精度損失。
  • 控制ONNX Runtime線程:雖然instance_group是主要的并行手段,您也可以在config.pbtxt中微調每個ONNX實例的線程數,但這屬于更高級的優化,通常保持默認或設置為較小值即可。
  • 將預處理/后處理移至客戶端:如示例所示,ONNX方案將分詞和池化操作放在客戶端。這降低了服務器的計算負載,但增加了客戶端的復雜性和依賴。

結論與對比

特性Python后端ONNX后端
性能較低較高 (原生C++執行,無Python開銷)
部署簡易度非常簡單 (無需模型轉換)較復雜 (需要導出為ONNX)
靈活性極高 (可在model.py中執行任意代碼)較低 (僅執行ONNX圖計算)
客戶端簡單 (只需發送文本)較復雜 (需要處理分詞和后處理)
優化潛力有限 (主要靠實例數)巨大 (圖優化、量化等)

建議

  • 如果您的首要目標是快速原型開發和最大靈活性,請選擇Python后端
  • 如果您的目標是追求極致的生產性能和吞吐量,請投入時間選擇ONNX后端,并探索其量化等高級優化。




當然,這是一個非常實際且常見的場景。將包含自定義預處理邏輯的復雜流水線部署到Triton,正是其強大功能的體現。在這種情況下,Python后端和ONNX后端的組合使用策略會變得更加清晰。

下面,我將為您分別提供兩種方案的超詳細部署步驟,以滿足您“文件 -> 解析 -> 分塊 -> Embedding”的流水線需求,并重點關注在32核CPU服務器上的性能優化。


方案一:純Python后端實現完整流水線 (一體化方案)

這種方法最為直接,將您所有的自定義代碼(文件解析、分塊)和模型調用邏輯全部封裝在一個Triton Python后端模型中。

架構思路:客戶端發送原始文件字節流,Triton服務器上的一個Python模型完成所有工作,然后返回最終的嵌入向量。

1. 拉取Triton Docker鏡像

這一步保持不變,確保獲取包含Python后端的鏡像。

# 將<xx.yy>替換為最新或您需要的版本,例如 24.06
docker pull nvcr.io/nvidia/tritonserver:<xx.yy>-py3
2. 準備模型倉庫

您需要一個模型目錄,其中包含model.py腳本、config.pbtxt配置文件,以及模型運行所需的依賴。

  1. 創建目錄結構

    # 創建模型和版本目錄
    mkdir -p model_repository/full_pipeline_py/1# 創建一個存放依賴的目錄 (可選但推薦)
    mkdir -p model_repository/full_pipeline_py/requirements
    
  2. 準備依賴
    由于Python后端默認環境中可能沒有sentence-transformers或文件解析庫(如pypdf2),您需要提供它們。最簡單的方式是創建一個requirements.txt文件。

    # 保存為 model_repository/full_pipeline_py/requirements.txt
    sentence-transformers
    # 如果您需要解析PDF,可以添加
    # pypdf2
    

    Triton會在加載模型時自動使用pip安裝這些依賴。

  3. 創建model.py腳本 (核心)
    這個腳本將實現您的完整流水線。

    # 保存為 model_repository/full_pipeline_py/1/model.py
    import json
    import numpy as np
    import torch
    from sentence_transformers import SentenceTransformer
    import triton_python_backend_utils as pb_utils
    import io
    # 示例:如果您需要解析PDF,可以導入
    # from PyPDF2 import PdfReaderclass TritonPythonModel:def initialize(self, args):"""在模型加載時調用一次,用于加載模型和設置參數。"""# 關鍵性能優化:在多實例CPU部署中,限制每個實例的PyTorch線程數# 避免實例間線程競爭,讓Triton的進程級并行發揮最大作用。torch.set_num_threads(1)# 從模型目錄加載模型,強制使用CPU# 'args['model_repository']' 指向 /models/full_pipeline_py/self.model = SentenceTransformer(args['model_repository'], device='cpu')print('SentenceTransformer model loaded on CPU.')def _parse_and_chunk(self, file_bytes):"""私有輔助函數,用于實現文件解析和分塊邏輯。這是一個示例,您需要根據您的文件類型替換這里的邏輯。"""# --- 在這里實現您復雜的文件解析邏輯 ---# 示例1:假設輸入是簡單的txt文件try:text = file_bytes.decode('utf-8')except UnicodeDecodeError:text = "Error decoding file content."# 示例2:如果您處理PDF (需要安裝PyPDF2)# text = ""# with io.BytesIO(file_bytes) as f:#     reader = PdfReader(f)#     for page in reader.pages:#         text += page.extract_text()# --- 在這里實現您的分塊邏輯 ---# 示例:按段落分塊chunks = [chunk for chunk in text.split('\n\n') if chunk.strip()]if not chunks:return [""] # 保證至少有一個空字符串塊,避免后續處理失敗return chunksdef execute(self, requests):"""處理每一批推理請求。"""responses =# Triton會將多個客戶端請求合并到'requests'列表中for request in requests:# 1. 從請求中獲取輸入張量 (原始文件字節)in_file_bytes_tensor = pb_utils.get_input_tensor_by_name(request, "RAW_FILE")# as_numpy()返回一個包含字節對象的NumPy數組,我們處理批次中的每個文件# 對于max_batch_size > 1,這里可能包含多個文件file_bytes_list = in_file_bytes_tensor.as_numpy()all_embeddings =for file_bytes in file_bytes_list:# 2. 對每個文件執行解析和分塊text_chunks = self._parse_and_chunk(file_bytes)# 3. 使用模型對所有塊進行推理# model.encode 本身支持批處理,效率很高chunk_embeddings = self.model.encode(text_chunks, convert_to_numpy=True)# 4. (可選) 聚合結果,例如,可以對所有塊的嵌入向量求平均final_embedding = np.mean(chunk_embeddings, axis=0)all_embeddings.append(final_embedding)# 5. 創建輸出張量# 將列表中的所有最終嵌入向量堆疊成一個批處理out_tensor = pb_utils.Tensor("FINAL_EMBEDDING", np.stack(all_embeddings).astype(np.float32))# 6. 創建并添加響應inference_response = pb_utils.InferenceResponse(output_tensors=[out_tensor])responses.append(inference_response)return responses
    
  4. 創建config.pbtxt配置文件
    此配置是性能優化的關鍵,我們將創建大量實例來利用32個CPU核心。

    # 保存為 model_repository/full_pipeline_py/config.pbtxt
    name: "full_pipeline_py"
    backend: "python"
    max_batch_size: 32 # 允許服務器同時處理多達32個文件請求input # 整個流水線的輸入是原始文件字節}
    ]output # 整個流水線的輸出是最終的聚合嵌入向量}
    ]# --- 性能優化配置 ---
    # 為32核CPU創建大量模型實例以實現最大并行度。
    # 每個實例都是一個獨立的Python進程,可以并行處理請求。
    instance_group# 動態批處理:對于文件處理依然有用。
    # 它會將多個獨立的文件請求打包成一個批次,一次性傳遞給execute方法。
    dynamic_batching {max_queue_delay_microseconds: 10000 # 10毫秒延遲換取更大批次preferred_batch_size: 
    }
    
3. 啟動Triton服務器 (CPU模式)
docker run --rm -p 8000:8000 -p 8001:8001 -p 8002:8002 \
-v $(pwd)/model_repository:/models \
nvcr.io/nvidia/tritonserver:<xx.yy>-py3 \
tritonserver --model-repository=/models
4. 編寫并行客戶端

客戶端非常簡單,只需讀取文件并發送即可。為了壓測服務器,我們同樣使用asyncio來模擬大量并發用戶。

# client_py_pipeline.py
import asyncio
import aiohttp
import timeSERVER_URL = "http://localhost:8000/v2/models/full_pipeline_py/infer"
FILE_PATH = "path/to/your/sample.txt" # 替換為您的示例文件路徑
CONCURRENT_REQUESTS = 100 # 模擬100個并發請求async def send_request(session, file_bytes):payload = {"inputs":,"datatype": "BYTES","data": [file_bytes.decode('latin-1')] # 使用aiohttp時需要這樣編碼}]}async with session.post(SERVER_URL, json=payload) as response:if response.status == 200:result = await response.json()return resultelse:print(f"Error: {response.status}")return Noneasync def main():with open(FILE_PATH, "rb") as f:file_bytes = f.read()async with aiohttp.ClientSession() as session:tasks =start_time = time.time()results = await asyncio.gather(*tasks)end_time = time.time()print(f"Sent {CONCURRENT_REQUESTS} concurrent requests in {end_time - start_time:.2f} seconds.")success_count = len([r for r in results if r])print(f"Received {success_count} successful responses.")if __name__ == "__main__":asyncio.run(main())

方案二:混合后端實現流水線 (性能優化方案)

這種方法更先進,也更復雜。它將流水線拆分為兩個部分,分別由最適合的后端處理:

  1. Python后端 (Orchestrator):負責處理文件IO、解析、分塊這些靈活的自定義邏輯。
  2. ONNX后端 (Accelerator):負責執行計算密集型的Embedding任務,性能遠超Python。

架構思路:客戶端發送文件 -> Python模型接收、解析、分塊 -> Python模型在服務器內部調用ONNX模型進行推理 -> Python模型聚合結果 -> 返回給客戶端。

1. 轉換模型為ONNX格式

這一步是前提。

pip install optimum[exporters]
optimum-cli export onnx --model BAAI/bge-base-en-v1.5 --task feature-extraction./embedding_onnx_model
2. 準備模型倉庫 (包含兩個模型)
  1. 創建目錄結構

    # 為ONNX模型創建目錄
    mkdir -p model_repository/embedding_onnx/1
    mv./embedding_onnx_model/model.onnx model_repository/embedding_onnx/1/# 為Python編排器模型創建目錄
    mkdir -p model_repository/pipeline_orchestrator/1
    
  2. 配置embedding_onnx模型
    這個模型是內部服務,負責高性能計算。

    • config.pbtxt for embedding_onnx:
      # 保存為 model_repository/embedding_onnx/config.pbtxt
      name: "embedding_onnx"
      backend: "onnxruntime"
      max_batch_size: 256 # 可以處理非常大的批次(所有文件的所有塊)input # 動態批處理, 動態序列長度},{name: "attention_mask"data_type: TYPE_INT64dims: [ -1, -1 ]}
      ]output}
      ]# --- 性能優化配置 ---
      # 同樣創建大量實例來利用CPU核心
      instance_group
      
  3. 配置pipeline_orchestrator模型
    這個模型是流水線的入口,負責編排。

    • 準備依賴

      # 保存為 model_repository/pipeline_orchestrator/requirements.txt
      transformers # 只需要分詞器
      # pypdf2 # 如果需要
      
    • model.py for pipeline_orchestrator (核心):

      # 保存為 model_repository/pipeline_orchestrator/1/model.py
      import json
      import numpy as np
      import triton_python_backend_utils as pb_utils
      from transformers import AutoTokenizerclass TritonPythonModel:def initialize(self, args):"""加載分詞器等。"""self.tokenizer = AutoTokenizer.from_pretrained("BAAI/bge-base-en-v1.5")print('Tokenizer loaded.')def _parse_and_chunk(self, file_bytes):# 這部分邏輯與方案一完全相同text = file_bytes.decode('utf-8')chunks = [chunk for chunk in text.split('\n\n') if chunk.strip()]return chunks if chunks else [""]def _mean_pooling(self, model_output, attention_mask):# ONNX模型輸出后處理token_embeddings = model_outputinput_mask_expanded = np.expand_dims(attention_mask, -1).repeat(token_embeddings.shape[-1], -1)sum_embeddings = np.sum(token_embeddings * input_mask_expanded, 1)sum_mask = np.clip(input_mask_expanded.sum(1), a_min=1e-9, a_max=None)return sum_embeddings / sum_maskasync def execute(self, requests):"""異步執行,可以并行處理對內部ONNX模型的調用。"""responses =# 異步處理所有請求for request in requests:# 1. 解析和分塊 (與方案一相同)in_file_bytes_tensor = pb_utils.get_input_tensor_by_name(request, "RAW_FILE")file_bytes_list = in_file_bytes_tensor.as_numpy()all_final_embeddings =for file_bytes in file_bytes_list:text_chunks = self._parse_and_chunk(file_bytes)# 2. 客戶端分詞encoded_input = self.tokenizer(text_chunks, padding=True, truncation=True, return_tensors='np')# 3. 構造對內部ONNX模型的推理請求infer_request = pb_utils.InferenceRequest(model_name='embedding_onnx',requested_output_names=['last_hidden_state'],inputs=),pb_utils.Tensor('attention_mask', encoded_input['attention_mask'])])# 4. 發送內部請求并等待響應 (異步執行)infer_response = await infer_request.async_exec()if infer_response.has_error():raise pb_utils.TritonModelException(infer_response.error().message())# 5. 從響應中提取結果并進行后處理last_hidden_state = pb_utils.get_output_tensor_by_name(infer_response, 'last_hidden_state').as_numpy()chunk_embeddings = self._mean_pooling(last_hidden_state, encoded_input['attention_mask'])# 6. 聚合結果final_embedding = np.mean(chunk_embeddings, axis=0)all_final_embeddings.append(final_embedding)# 7. 創建最終輸出out_tensor = pb_utils.Tensor("FINAL_EMBEDDING", np.stack(all_final_embeddings).astype(np.float32))inference_response = pb_utils.InferenceResponse(output_tensors=[out_tensor])responses.append(inference_response)return responses
      
    • config.pbtxt for pipeline_orchestrator:

      # 保存為 model_repository/pipeline_orchestrator/config.pbtxt
      name: "pipeline_orchestrator"
      backend: "python"
      max_batch_size: 32input}
      ]output}
      ]
      # 注意:這個編排器模型通常不需要自己的instance_group,
      # 因為它的主要瓶頸在于它調用的ONNX模型。
      # 并行性由ONNX模型的多個實例來保證。
      
3. 啟動Triton服務器

命令完全相同,Triton會自動加載這兩個模型。

docker run --rm -p 8000:8000 -p 8001:8001 -p 8002:8002 \
-v $(pwd)/model_repository:/models \
nvcr.io/nvidia/tritonserver:<xx.yy>-py3 \
tritonserver --model-repository=/models
4. 編寫并行客戶端

好消息是,客戶端代碼與方案一完全相同! 所有的復雜性都被封裝在了服務器端。客戶端只需要調用pipeline_orchestrator模型即可,它并不知道內部還有一個ONNX模型。


結論與最終建議

特性方案一 (純Python)方案二 (混合后端)
性能中等
部署復雜度
代碼維護簡單 (所有邏輯在一個文件)復雜 (邏輯分散在兩個模型)
靈活性極高極高
資源利用最佳 (為不同任務使用最優后端)

給您的建議:

  1. 從方案一開始:首先實現純Python后端的流水線。它更容易調試,能讓您快速驗證整個流程的正確性。對于中等負載,通過增加instance_groupcount,它的性能可能已經足夠滿足您的需求。

  2. 當性能成為瓶頸時,再轉向方案二:如果您的QPS(每秒查詢率)要求非常高,或者單個請求的延遲需要被極致壓縮,那么投入精力去實現混合后端方案是值得的。它將計算最密集的部分交給了最高效的ONNX后端,能最大化您32核CPU的吞吐能力。

方案二代表了Triton更高級的用法,是實現生產級高性能服務的理想架構。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/92937.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/92937.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/92937.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java動態調試技術原理

本文轉載自 美團技術團隊胡健的Java 動態調試技術原理及實踐, 通過學習java agent方式進行動態調試了解目前很多大廠開源的一些基于此的調試工具。 簡介 斷點調試是我們最常使用的調試手段&#xff0c;它可以獲取到方法執行過程中的變量信息&#xff0c;并可以觀察到方法的執…

人工智能-python-OpenCV 圖像基礎認知與運用

文章目錄OpenCV 圖像基礎認知與運用1. OpenCV 簡介與安裝OpenCV 的優勢安裝 OpenCV2. 圖像的基本概念2.1. 圖像的存儲格式2.2. 圖像的表示3. 圖像的基本操作3.1. 創建圖像窗口3.2. 讀取與顯示圖像3.3. 保存圖像3.4. 圖像切片與區域提取3.5. 圖像大小調整4. 圖像繪制與注釋4.1. …

Windows電腦添加、修改打印機的IP地址端口的方法

本文介紹在Windows電腦中&#xff0c;為打印機添加、修改IP地址&#xff0c;從而解決電腦能找到打印機、但是無法打印問題的方法。最近&#xff0c;辦公室的打印機出現問題——雖然在電腦的打印機列表能找到這個打印機&#xff0c;但是選擇打印時&#xff0c;就會顯示文檔被掛起…

告別復雜配置!Spring Boot優雅集成百度OCR的終極方案

1. 準備工作 1.1 注冊百度AI開放平臺 訪問百度AI開放平臺 注冊賬號并登錄 進入控制臺 → 文字識別 → 創建應用 記錄下API Key和Secret Key 2. 項目配置 2.1 添加依賴 (pom.xml) <dependencies><!-- Spring Boot Web --><dependency><groupId>o…

「iOS」——內存五大分區

UI學習iOS-底層原理 24&#xff1a;內存五大區總覽一、棧區&#xff08;Stack&#xff09;1.1 核心特性1.2 優缺點1.3函數棧與棧幀1.3 堆棧溢出風險二、堆區&#xff08;Heap&#xff09;;2.1 核心特性2.2 與棧區對比三、全局 / 靜態區&#xff08;Global/Static&#xff09;3.…

每日一題【刪除有序數組中的重復項 II】

刪除有序數組中的重復項 II思路class Solution { public:int removeDuplicates(vector<int>& nums) {if(nums.size()<2){return nums.size();}int index 2;for (int i 2; i < nums.size();i ) {if(nums[i] ! nums[index-2]) {nums[index]nums[i];}}return ind…

兼容性問題記錄

1、dialog設置高度MATCH_PARENT全屏后&#xff0c;三星機型和好像是一加&#xff0c;會帶出頂部狀態欄&#xff0c;設置隱藏狀態欄屬性無效。解決方法&#xff1a;高度不設置為MATCH_PARENT&#xff0c;通過windowmanager.getdefaultdisplay來獲取并設置高度&#xff0c;再設置…

6.數組和字符串

在C語言中&#xff0c;數組和字符串是基礎且重要的概念。它們用于存儲和操作一系列相同類型的元素或字符序列。數組1. 數組定義與初始化數組是一系列相同類型的數據項的集合&#xff0c;這些數據項可以通過一個共同的名字來引用。數組中的每個元素都有一個索引&#xff08;也稱…

odoo代碼分析(一)

Odoo 是一套基于網絡的開放式源代碼商業應用套件,既可以作為獨立應用運行,也可以作為集成的全功能 ERP 系統使用。Odoo 平臺采用模塊化架構,允許組織根據自身需求起步,并在需求增長時擴展功能。 什么是 Odoo? Odoo 提供了一個完整的商業應用生態系統,包括: 客戶關系管…

從“人工眼”到‘智能眼’:EZ-Vision視覺系統如何重構生產線視覺檢測精度?

制造業是我國實體經濟的基礎&#xff0c;是國內經濟增長的重要引擎。制造業智能化建設是當下的必然趨勢&#xff0c;然而目前依舊有很多中小型企業因為成本原因&#xff0c;無法加快智能化制造的步伐。在智能檢測領域更是如此&#xff0c;很多企業依舊在采用人工檢測&#xff0…

Etcd原理基礎學習

etcd 是一個開源的分布式鍵值存儲系統&#xff0c;專注于提供高可用性、強一致性的數據存儲與訪問&#xff0c;廣泛應用于分布式系統的服務發現、配置管理和協調任務。以下是其核心特性和應用場景的詳細介紹。接下來就看看Etcd如何實現服務注冊&#xff0c;以及如何通過Raft算法…

【硬件-筆試面試題】硬件/電子工程師,筆試面試題-32,(知識點:模數轉換器,信噪比,計算公式,)

目錄 1、題目 2、解答 步驟一&#xff1a;明確理想 ADC 的信噪比公式 步驟二&#xff1a;推導公式的來源 步驟三&#xff1a;得出答案 3、相關知識點 一、信噪比&#xff08;SNR&#xff09;的定義 二、理想 ADC 的量化噪聲 三、滿量程正弦波信號的功率 四、信噪比公…

Redis過期數據的刪除策略是什么?有哪些?

定時刪除&#xff1a;- 每個設置了TTL的key中都會創建一個計時器&#xff0c;等到過期時間就會立即刪除- 對內存友好&#xff0c;但是會占用大量的CPU資源去處理過期數據&#xff0c;從而影響緩存的吞吐量和響應時間惰性刪除&#xff1a;- 設置了key的過期后&#xff0c;不會立…

linux dd命令詳解

dd 是一個功能強大的 Unix/Linux 命令行工具&#xff0c;用于低級別的字節流操作&#xff0c;常用于創建、復制、轉換和處理文件或設備數據。它在 macOS 和 Linux 系統上都可用&#xff0c;但在 macOS 上有一些細微差異。本文將詳細講解 dd 命令的用法&#xff0c;包括參數、常…

多線程同步技術是用于協調多個線程訪問共享資源或執行順序的機制,以避免數據競爭、死鎖、線程不安全等問題

多線程同步技術是用于協調多個線程訪問共享資源或執行順序的機制,以避免數據競爭、死鎖、線程不安全等問題。 在提供的代碼中,存在多線程操作加熱板的場景,涉及鎖競爭和硬件資源訪問,優化多線程同步可以顯著提升程序性能和穩定性。 以下是多線程同步技術的詳細解釋、常見…

CRMEB標準版,從創建數據表到實現最基礎增刪改查的實現過程

很多使用了CRMEB單商戶系統的童鞋在進行二開的時候&#xff0c;都會遇到新建了數據表之后不知道對數據表怎么進行操作。那么&#xff0c;這篇文章將帶你完整的實現一遍&#xff0c;以后就不會怕啦。一、創建數據表就以最簡單的為例&#xff0c;創建一個學生的信息表編號姓名性別…

J2EE模式---數據訪問對象模式

數據訪問對象模式基礎概念數據訪問對象模式&#xff08;Data Access Object Pattern&#xff0c;簡稱 DAO 模式&#xff09;是一種結構型設計模式&#xff0c;其核心思想是將數據訪問邏輯與業務邏輯分離&#xff0c;通過一個抽象層&#xff08;DAO&#xff09;來處理數據的持久…

【OpenCV篇】OpenCV——02day.圖像預處理(1)

目錄 前言 一、圖像色彩空間轉換 1 RGB顏色空間 2 顏色加法 3 顏色加權加法 4 HSV顏色空間 5 RGB轉Gray(灰度) 二、灰度實驗 1 灰度圖 2 最大值法 3 平均值法 4 加權均值法 5 兩個極端的灰度值 三、圖像二值化處理 二值圖像 1 閾值法(THRESH_BINARY) 2 反閾值…

經典IDE之Turbo C

寫的程序不多&#xff0c;換過的 IDE 不少&#xff0c;本文將列舉曾經用過的不同 C 語言相關的 IDE 環境&#xff0c;既是紀念&#xff0c;也是回憶。值得注意的是 IDE 的出現是為了提高開發效率&#xff0c;有一個相對成熟的編譯環境和程序。從編程的角度來看&#xff0c;過分…

Go 多模塊倉庫標簽管理教程

為了方便自己開發&#xff0c;自己寫了個小工具&#xff1a;DzhGO 代碼生成工具 功能特點標題 初始化項目基礎結構生成插件模塊代碼生成模型和實體代碼生成服務接口和實現代碼支持 admin 和 app 兩種模塊類型生成項目基礎目錄 具體介紹看倉庫&#xff1a; https://github.co…