Run an ONNX model with more than one input or output through OneModel’s Session: list its inputs and outputs, pass named tensors in any order, and get the outputs back as tensors.
The model is scorer.onnx from the sample models: score = features × W + bias and best, the largest score of each row.
using RecursiveAI.OneModel.Graph; using RecursiveAI.OneModel.Tensors; using var session = Session.Load("scorer.onnx"); foreach (var i in session.Inputs) Console.WriteLine($"in {i.Name}: {i.DType} [{string.Join(", ", i.Dims)}]"); foreach (var o in session.Outputs) Console.WriteLine($"out {o.Name}: {o.DType} [{string.Join(", ", o.Dims)}]"); using var features = Tensor.FromSpan<float>([1f, 2f, 3f, 4f, 5f, 6f], Shape.Create(2, 3)); using var bias = Tensor.FromSpan<float>([0.5f, 1.5f], Shape.Create(1, 2)); var outputs = new Tensor[2]; // empty: the session allocates them, and we dispose them session.Run(["bias", "features"], [bias, features], ["score", "best"], outputs); using Tensor score = outputs[0], best = outputs[1]; Console.WriteLine($"score {score.Shape}: {string.Join(", ", score.Data<float>().ToArray())}"); Console.WriteLine($"best {best.Shape}: {string.Join(", ", best.Data<float>().ToArray())}");
in features: F32 [batch, 3] in bias: F32 [1, 2] out score: F32 [batch, 2] out best: F32 [batch] score [2,2]: 4.5, 6.5, 10.5, 12.5 best [2]: 6.5, 12.5
How Session.Run works
- Every model input is passed once, by name, in any order. Inputs are read, never changed and not kept.
- Each element of
outputsreceives the output named at the same position. An emptyTensoris replaced by a new one that you own and dispose; a tensor of the right type and shape is overwritten in place, so a loop can reuse its outputs. batchis a symbolic dimension: the session makes a plan for each set of input shapes it sees and caches it (16 by default,SessionOptions.MaxCachedPlans).- A wrong name, element type or shape is a
SessionException(InvalidInput) before anything runs.
For a model with one input and one output, the span form session.Run<float, float>(inputName, input, shape, outputName, output) copies in and out of your buffers and allocates nothing once warm. Sessions are thread-safe. More in sessions and plans.