跳到主要内容

推理

ai.infer("a.jpg")?; ai.infer(&bytes)?; ai.infer(&dynamic_image)?;

调用失败错误写进 last_error(),成功即清空,Phase 保持 Opened。

快速开始​

let mut ai = Model::new("model.darmodel")?;
ai.open(None)?;
let inf = ai.infer_file("a.jpg", None)?;
println!("{inf:?}");

方法​

类别方法类型读写说明
推理infer_file()Result<InferenceResult, AiError>写读取图片文件并推理
推理infer_image()Result<String, AiError>写对内存里的图像推理
推理infer_buffer()Result<String, AiError>写对裸像素缓冲推理
Sessioninfer_tensors()Result<Vec<Tensor>, Error>写多输入张量推理(属于 Session 高级面,不是 Model 的成员)
控制cancel()Result<(), AiError>写取消正在跑的或下一次推理
并发submit()Result<u64, AiError>写提交一张图进去,返回任务句柄
并发wait()Result<String, AiError>写等待结果 JSON
并发set_device_weight()Result<(), Error>写运行时改每张卡的权重,只影响之后提交的任务

infer_file()​

pub fn infer_file(&self, image_path: impl AsRef<Path>, thresholds: Option<&LabelThresholds>)
-> Result<InferenceResult, AiError>

支持 JPG、PNG、BMP,格式自动识别。

参数:

  • image_path (impl AsRef<Path>) — 图片文件路径
  • thresholds (Option<&LabelThresholds>) — 只覆盖这一次调用的阈值。传 None 就用实例默认表

示例:

for path in ["a.jpg", "b.jpg", "c.jpg"] {
match ai.infer_file(path, None) {
Ok(inf) => println!("{inf:?}"),
Err(e) => eprintln!("{path} 失败: {}", e.message),
}
}

infer_image()​

pub fn infer_image(&self, image: &[u8], desc: &ImageDesc, thresholds: Option<&LabelThresholds>)
-> Result<String, AiError>

编码过的字节配 ImageDesc::auto()。

参数:

  • image (&[u8]) — 图片字节(编码流或裸像素)
  • desc (&ImageDesc) — 图像描述
  • thresholds (Option<&LabelThresholds>) — 同 infer_file

示例:

let json = ai.infer_image(&photo, &ImageDesc::auto(), None)?;
println!("{json}");

infer_buffer()​

pub fn infer_buffer(&self, data: &[u8], desc: &ImageDesc, thresholds: Option<&LabelThresholds>) -> Result<String, AiError>

这是裸像素缓冲的入口,比如相机缓冲或内存位图。data 是像素字节,宽高与格式写进 ImageDesc。

参数:

  • data (&[u8]) — 像素字节
  • desc (&ImageDesc) — 宽高与格式必填(裸缓冲禁 Auto)
  • thresholds (Option) — 本次阈值覆盖

示例:

use darra_ai::ImageDesc;
match m.infer_buffer(&raw, &ImageDesc::rgb888(640, 480, 0), None) {
Ok(json) => println!("{json}"),
Err(e) => eprintln!("推理失败 {} {}", e.code, e.message),
}

infer_tensors()​

pub fn infer_tensors(&self, inputs: &[Tensor]) -> Result<Vec<Tensor>, Error>

这是 Session 的方法(不在 Model 上),直接把张量喂给模型。

参数:

  • inputs (&[Tensor]) — 输入张量列表,name 对齐 schema I/O 名

示例:

match session.infer_tensors(&[input]) {
Ok(outs) => println!("输出 {} 个张量", outs.len()),
Err(Error::MetaMismatch { message, .. }) => eprintln!("与模型对不上: {message}"),
Err(e) => eprintln!("张量推理失败: {}", e.message()),
}

cancel()​

pub fn cancel(&self) -> Result<(), AiError>

取消正在跑的或下一次推理的可中断等待,取消标志用一次就消耗掉。未 open 先取消属参数契约违反。

参数: 无

示例:

// 在飞取消:另起线程调用
let h = std::thread::spawn(|| {
if let Err(e) = m.cancel() {
eprintln!("取消失败 {} {}", e.code, e.message);
}
});

阈值​

default_thresholds 是实例的默认表。标签名映射到分数下限 [0,1]。

let t = LabelThresholds::from_pairs([("缺陷", 0.5), ("划痕", 0.8)])?;
ai.set_default_thresholds(t)?;
let one = LabelThresholds::from_pairs([("缺陷", 0.9)])?;
match ai.infer_file("a.jpg", Some(&one)) {
Ok(inf) => println!("{inf:?}"),
Err(e) => eprintln!("{} {}", e.code, e.message),
}

并发推理​

一个 Model 只装一个模型。要跑两个模型,建两个实例,各自 open。

空闲机实测(197,det.onnx,3 轮中位):

  • 单任务基线:1×(约 0.2s)
  • 池 workers=2 双投:两任务同时完成,各约 1–1.5 倍单任务
  • 多实例 2–4 个:总吞吐约等于串行(0.88–0.94×) 并发收益随机器负载变化。

submit​

pub fn submit(&self, image: &[u8], desc: &ImageDesc) -> Result<u64, AiError>

把一张图提交进池队列,立即返回 ticket(u64)。图像字节会被拷走,所以入参切片在返回后就可以释放。

参数:

  • image (&[u8]) — 图像字节(编码流或裸像素)
  • desc (&ImageDesc) — 图像描述

示例:

let t = m.submit(&bytes, &ImageDesc::auto())?;

wait​

pub fn wait(&self, ticket: u64) -> Result<String, AiError>

按 ticket 取这个任务的结果 JSON,会阻塞到任务完成或等待预算耗尽。

参数:

  • ticket (u64) — submit 返回的票据,必填

示例:

let json = m.wait(t)?;

set_device_weight()​

pub fn set_device_weight(&self, gpu_device: i32, weight: i32) -> Result<(), Error>

这个方法在运行期修改某张卡的权重。传 1 到 10000 表示新权重。

参数:

  • gpu_device (i32) — GPU 卡号
  • weight (i32) — 新权重,1 到 10000

示例:

pool.set_device_weight(1, 50)?;

线程安全​

不同的会话互不干扰,可以并发调用。Drop 只在没有正在执行的调用时才会真正释放。

队列满与挤掉(overflow 三态)​

InferOverflow 有三个值。Fail 是默认,submit 立即失败。

现象返回处置
Fail 队列满的 submitError::Busy加大 queue_capacity,或降低提交速率
DropOldest 挤掉后 wait 取该票Error::Busy计入 report 的 dropped;要保帧用 Fail 或加大 queue_capacity
try_wait 还没好Error::Busy轮询重试,或改用 wait 阻塞取
等待预算耗尽Error::Timeout加大 timeout_ms 或降并发。深层 Provider Run 不受这条裁决
被 cancel() / 协作标志打断Error::Cancelled被取消帧按丢帧处理
缺 Provider 运行时包Error::ProviderMissing装对应 Provider 运行时包