| """
|
| bert/trt_session.py
|
| TensorRT ORT session with optimization profiles.
|
|
|
| Profiles define min/opt/max tensor shapes so TRT compiles the most efficient
|
| CUDA kernels for the expected (batch_size, sequence_length) distribution.
|
| First load: ~5 min to compile the .plan engine.
|
| Subsequent loads: instant from cache.
|
| """
|
|
|
| from __future__ import annotations
|
|
|
| import argparse
|
| import numpy as np
|
| from pathlib import Path
|
| from typing import Dict, List, Tuple
|
|
|
| import numpy as np
|
|
|
|
|
| def build_trt_session(
|
| model_path: str | Path,
|
| cache_dir: str | Path = "./trt_cache",
|
| device_id: int = 0,
|
|
|
| min_shape: Tuple[int, int] = (1, 16),
|
| opt_shape: Tuple[int, int] = (32, 128),
|
| max_shape: Tuple[int, int] = (128, 512),
|
| ) -> "ort.InferenceSession":
|
| """
|
| Build an ORT InferenceSession backed by TensorrtExecutionProvider.
|
|
|
| The engine is cached to `cache_dir` after first compilation so
|
| subsequent cold-starts load in milliseconds.
|
| """
|
| try:
|
| import onnxruntime as ort
|
| except ImportError:
|
| raise RuntimeError("pip install onnxruntime-gpu")
|
|
|
| Path(cache_dir).mkdir(parents=True, exist_ok=True)
|
|
|
| trt_providers = [
|
| (
|
| "TensorrtExecutionProvider",
|
| {
|
| "device_id": device_id,
|
| "trt_fp16_enable": True,
|
| "trt_engine_cache_enable": True,
|
| "trt_engine_cache_path": str(cache_dir),
|
|
|
| "trt_profile_min_shapes": f"input_ids:{min_shape[0]}x{min_shape[1]},attention_mask:{min_shape[0]}x{min_shape[1]},token_type_ids:{min_shape[0]}x{min_shape[1]}",
|
| "trt_profile_opt_shapes": f"input_ids:{opt_shape[0]}x{opt_shape[1]},attention_mask:{opt_shape[0]}x{opt_shape[1]},token_type_ids:{opt_shape[0]}x{opt_shape[1]}",
|
| "trt_profile_max_shapes": f"input_ids:{max_shape[0]}x{max_shape[1]},attention_mask:{max_shape[0]}x{max_shape[1]},token_type_ids:{max_shape[0]}x{max_shape[1]}",
|
| "trt_int8_enable": False,
|
| },
|
| ),
|
| "CUDAExecutionProvider",
|
| "CPUExecutionProvider",
|
| ]
|
|
|
| opts = ort.SessionOptions()
|
| opts.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
|
| opts.intra_op_num_threads = 4
|
|
|
| print(f"[trt_session] loading {model_path} ...")
|
| print(f"[trt_session] cache_dir={cache_dir} (first load may take ~5 min)")
|
| session = ort.InferenceSession(
|
| str(model_path),
|
| sess_options=opts,
|
| providers=trt_providers,
|
| )
|
| actual_providers = session.get_providers()
|
| print(f"[trt_session] active providers: {actual_providers}")
|
| return session
|
|
|
|
|
| def run_batch(
|
| session: "ort.InferenceSession",
|
| input_ids: np.ndarray,
|
| attention_mask: np.ndarray,
|
| token_type_ids: np.ndarray | None = None,
|
| ) -> np.ndarray:
|
| """
|
| Run one batch through the TRT session.
|
| Returns logits: (B, 3) float32.
|
| """
|
| if token_type_ids is None:
|
| token_type_ids = np.zeros_like(input_ids)
|
|
|
| feeds = {
|
| "input_ids": input_ids.astype(np.int64),
|
| "attention_mask": attention_mask.astype(np.int64),
|
| "token_type_ids": token_type_ids.astype(np.int64),
|
| }
|
| outputs = session.run(["logits"], feeds)
|
| return outputs[0]
|
|
|
|
|
| def softmax(x: np.ndarray) -> np.ndarray:
|
| e = np.exp(x - x.max(axis=-1, keepdims=True))
|
| return e / e.sum(axis=-1, keepdims=True)
|
|
|
|
|
| def entailment_scores(logits: np.ndarray) -> np.ndarray:
|
| """Softmax probability of Entailment class (index 2), shape (B,)."""
|
| return softmax(logits)[:, 2]
|
|
|
|
|
| if __name__ == "__main__":
|
| parser = argparse.ArgumentParser()
|
| parser.add_argument("--model", type=str, required=True, help="path to FP16 ONNX model")
|
| parser.add_argument("--cache", type=str, default="./trt_cache")
|
| args = parser.parse_args()
|
|
|
| session = build_trt_session(args.model, args.cache)
|
|
|
|
|
| ids = np.random.randint(0, 30000, (4, 128), dtype=np.int64)
|
| mask = np.ones((4, 128), dtype=np.int64)
|
| logits = run_batch(session, ids, mask)
|
| scores = entailment_scores(logits)
|
| print(f"[smoke test] entailment scores: {scores}")
|
|
|