Documentation
¶
Overview ¶
Package espresso provides high-level access to Apple's Espresso neural network execution framework with multi-backend support (CPU, GPU, ANE).
Unlike github.com/tmc/apple/x/ane, which targets only the Apple Neural Engine, Espresso can dispatch individual layers to the best available backend. This is the same execution path that CoreML uses internally.
ctx, err := espresso.Open()
if err != nil {
log.Fatal(err)
}
defer ctx.Close()
net, err := ctx.LoadNetwork(irJSON)
if err != nil {
log.Fatal(err)
}
defer net.Close()
f := espresso.NewFrame()
f.SetInput("input", data, espresso.Shape{Batch: 1, Channels: 3, Height: 224, Width: 224})
if err := net.Eval(f); err != nil {
log.Fatal(err)
}
output, _ := f.Output("output")
Architecture ¶
Espresso is Apple's private neural network IR and execution framework. It sits between CoreML/MIL and hardware backends (ANE, GPU via Metal Performance Shaders, CPU). Where x/ane provides direct ANE-only access, Espresso is the multi-backend orchestrator that CoreML uses internally.
The key advantage over x/ane is per-layer backend selection: Espresso can run some layers on ANE, fall back to GPU for unsupported ops, and use CPU as a last resort. x/ane requires the entire model to be ANE-compatible.
CoreML (.mlmodel) → Espresso IR (JSON + weights)
│
┌──────────┼──────────┐
ANE GPU CPU
Execution ¶
A Context manages execution state and selects the platform. Context.LoadNetwork loads a network from Espresso IR (JSON + binary weights). Frame binds named input and output tensors using string keys matching the model's tensor names. Network.Eval executes the network.
Profiling ¶
ProfileNetwork collects per-layer execution data including which engine ran each layer, runtime samples, and platform support. This is useful for understanding how Espresso partitions a model across backends.
Optimization Passes ¶
The Pass interface wraps Espresso's built-in optimization passes (fusion, strength reduction, quantization, normalization merging). Use Optimize to apply a standard set, or OptimizeWith for a custom pipeline.
Metal Interop ¶
For networks using the ANE backend, [Network.MetalBuffer] provides zero-copy GPU access to ANE IOSurfaces via Metal buffers.
Example (Argmax) ¶
package main
import (
"fmt"
"github.com/tmc/apple/x/espresso"
)
func main() {
data := []float32{0.1, 0.7, 0.2}
fmt.Println(espresso.Argmax(data))
}
Output: 1
Example (Softmax) ¶
package main
import (
"fmt"
"github.com/tmc/apple/x/espresso"
)
func main() {
data := []float32{1.0, 2.0, 3.0}
result := espresso.Softmax(data)
fmt.Printf("%.4f %.4f %.4f\n", result[0], result[1], result[2])
}
Output: 0.0900 0.2447 0.6652
Example (TopK) ¶
package main
import (
"fmt"
"github.com/tmc/apple/x/espresso"
)
func main() {
data := []float32{0.1, 0.9, 0.3, 0.7, 0.5}
top3 := espresso.TopK(data, 3)
fmt.Println(top3)
}
Output: [1 3 4]
Example (Types) ¶
package main
import (
"fmt"
"github.com/tmc/apple/x/espresso"
)
func main() {
fmt.Println(espresso.PlatformAuto)
fmt.Println(espresso.PlatformCPU)
fmt.Println(espresso.PlatformGPU)
fmt.Println(espresso.PlatformANE)
s := espresso.Shape{Batch: 1, Channels: 3, Height: 224, Width: 224}
fmt.Println(s.Elements())
fmt.Println(espresso.EngineCPU)
fmt.Println(espresso.EngineGPU)
fmt.Println(espresso.EngineANE)
}
Output: auto cpu gpu ane 150528 cpu gpu ane
Index ¶
- Variables
- func Argmax(data []float32) int
- func IsMemoryTight() bool
- func Optimize(_ *Network) error
- func OptimizeWith(_ *Network, _ ...Pass) error
- func Softmax(data []float32) []float32
- func TopK(data []float32, k int) []int
- type ANEProfile
- type ANESurface
- func (a *ANESurface) AliasingMem() any
- func (a *ANESurface) Cleanup()
- func (a *ANESurface) CreateIOSurface(_ any) uintptr
- func (a *ANESurface) ForceAlloc(_ any)
- func (a *ANESurface) IOSurfaceForFrame(_ uint64) (uintptr, error)
- func (a *ANESurface) LazilyAllocFrame(_ uint64)
- func (a *ANESurface) MatchesCVImageBuffer(_ uintptr) bool
- func (a *ANESurface) MatchesIOSurface(_ uintptr) bool
- func (a *ANESurface) NFrames() uint64
- func (a *ANESurface) PixelFormat() uint32
- func (a *ANESurface) ReadFrame(_ uint64, _ []byte) error
- func (a *ANESurface) ReadFrameF32(_ uint64, _ []float32) error
- func (a *ANESurface) ResizeForAsync(_ uint64)
- func (a *ANESurface) RestoreAllInternalStorage()
- func (a *ANESurface) RestoreInternalStorage(_ uint64)
- func (a *ANESurface) SetAliasingMem(_ any)
- func (a *ANESurface) SetExternalStorage(_ uint64, _ uintptr)
- func (a *ANESurface) WriteFrame(_ uint64, _ []byte) error
- func (a *ANESurface) WriteFrameF32(_ uint64, _ []float32) error
- type Builder
- func (b *Builder) Activation(name, mode string, opts ...LayerOption) *Builder
- func (b *Builder) BatchNorm(name string, channels int, opts ...LayerOption) *Builder
- func (b *Builder) Build() (netJSON []byte, shapeJSON []byte, err error)
- func (b *Builder) BuildWithWeights() (netJSON, shapeJSON, weightsBin []byte, err error)
- func (b *Builder) Concat(name string, opts ...LayerOption) *Builder
- func (b *Builder) Convolution(name string, nOutput, kernelH, kernelW int, opts ...LayerOption) *Builder
- func (b *Builder) Elementwise(name, operation string, opts ...LayerOption) *Builder
- func (b *Builder) ElementwiseOped(name string, op ElementwiseOp, opts ...LayerOption) *Builder
- func (b *Builder) InnerProduct(name string, nOutput int, opts ...LayerOption) *Builder
- func (b *Builder) Pooling(name, mode string, kernelH, kernelW int, opts ...LayerOption) *Builder
- func (b *Builder) Reshape(name string, shape [4]int, opts ...LayerOption) *Builder
- func (b *Builder) Softmax(name string, opts ...LayerOption) *Builder
- type Context
- type ContextOption
- type ElementwiseOp
- type Engine
- type Error
- type EvalOptions
- type Frame
- func (f *Frame) FunctionName() string
- func (f *Frame) InputNames() []string
- func (f *Frame) Output(_ string) ([]float32, error)
- func (f *Frame) OutputFloat64(_ string) ([]float64, error)
- func (f *Frame) OutputInto(_ string, _ []float32) error
- func (f *Frame) OutputNames() []string
- func (f *Frame) OutputRaw(_ string) ([]byte, error)
- func (f *Frame) SetFunctionName(_ string)
- func (f *Frame) SetGroundTruth(_ string, _ []float32, _ Shape) error
- func (f *Frame) SetInput(_ string, _ []float32, _ Shape) error
- func (f *Frame) SetInputBytes(_ string, _ []byte) error
- func (f *Frame) SetInputCVPixelBuffer(_ string, _ uintptr) error
- func (f *Frame) SetInputIOSurface(_ string, _ uintptr) error
- func (f *Frame) SetInputImage(_ string, _ []byte, _ int) error
- type FrameStorage
- type LayerOption
- func WithBias(data []float32) LayerOption
- func WithBottom(names ...string) LayerOption
- func WithGroups(g int) LayerOption
- func WithHasReLU(v bool) LayerOption
- func WithPad(t, b, l, r int) LayerOption
- func WithStride(h, w int) LayerOption
- func WithTop(names ...string) LayerOption
- func WithWeights(data []float32) LayerOption
- type LayerProfile
- type LayerShape
- type MetalDevice
- type Network
- func (n *Network) Close() error
- func (n *Network) Eval(_ *Frame) error
- func (n *Network) EvalAsync(_ *Frame) <-chan error
- func (n *Network) EvalAsyncWithCallback(_ *Frame, fn func(error))
- func (n *Network) EvalWithOptions(_ *Frame, _ EvalOptions) error
- func (n *Network) EvalWithStorage(_ *FrameStorage, _ EvalOptions) error
- func (n *Network) HasLayer(_ string) bool
- func (n *Network) LayerCount() int
- func (n *Network) LayerNames() []string
- type NetworkOption
- type Pass
- type Platform
- type Profile
- func (p *Profile) ANEResidentLayers() []LayerProfile
- func (p *Profile) CPUFallbackLayers() []LayerProfile
- func (p *Profile) IsFullyANEResident() bool
- func (p *Profile) LayersByEngine() map[Engine][]LayerProfile
- func (p *Profile) TotalRuntimeMS() float64
- func (p *Profile) UnsupportedLayers() []LayerProfile
- type Shape
- type ShapeMap
- type SurfaceLayout
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrFramework = errors.New("espresso: framework not available") ErrLoad = errors.New("espresso: network load failed") ErrNilNetwork = errors.New("espresso: nil network returned") ErrEval = errors.New("espresso: evaluation failed") ErrBindInput = errors.New("espresso: input binding failed") ErrBindOutput = errors.New("espresso: output binding failed") ErrNoSuchOutput = errors.New("espresso: output not found") ErrClosed = errors.New("espresso: context closed") )
var ErrUnsupported = errors.New("espresso: unsupported platform")
ErrUnsupported is returned on platforms that do not support Espresso.
Functions ¶
func IsMemoryTight ¶
func IsMemoryTight() bool
IsMemoryTight returns whether Espresso's shared Metal singleton reports memory pressure.
func OptimizeWith ¶
OptimizeWith applies the given passes in order.
Types ¶
type ANEProfile ¶
ANEProfile contains ANE-specific profiling data.
type ANESurface ¶
type ANESurface struct{}
ANESurface provides access to Espresso's ANE IOSurface for zero-copy Metal buffer creation and multi-buffer async execution.
func NewANESurface ¶
func NewANESurface() *ANESurface
NewANESurface creates a new ANE IOSurface wrapper.
func NewANESurfaceFromLayout ¶
func NewANESurfaceFromLayout(_ SurfaceLayout) *ANESurface
NewANESurfaceFromLayout creates an ANE IOSurface with explicit model-driven dimensions.
func NewANESurfaceWithProperties ¶
func NewANESurfaceWithProperties(_, _ any) *ANESurface
NewANESurfaceWithProperties creates an ANE IOSurface with specific properties and pixel formats.
func (*ANESurface) AliasingMem ¶
func (a *ANESurface) AliasingMem() any
AliasingMem returns the external storage blob used for aliasing memory.
func (*ANESurface) CreateIOSurface ¶
func (a *ANESurface) CreateIOSurface(_ any) uintptr
CreateIOSurface creates a new IOSurface with optional extra properties.
func (*ANESurface) ForceAlloc ¶
func (a *ANESurface) ForceAlloc(_ any)
ForceAlloc forces non-lazy allocation.
func (*ANESurface) IOSurfaceForFrame ¶
func (a *ANESurface) IOSurfaceForFrame(_ uint64) (uintptr, error)
IOSurfaceForFrame returns the IOSurface backing the given multi-buffer frame.
func (*ANESurface) LazilyAllocFrame ¶
func (a *ANESurface) LazilyAllocFrame(_ uint64)
LazilyAllocFrame lazily allocates an IOSurface for the given frame.
func (*ANESurface) MatchesCVImageBuffer ¶
func (a *ANESurface) MatchesCVImageBuffer(_ uintptr) bool
MatchesCVImageBuffer returns whether the surface matches a CVImageBuffer.
func (*ANESurface) MatchesIOSurface ¶
func (a *ANESurface) MatchesIOSurface(_ uintptr) bool
MatchesIOSurface returns whether the surface matches an IOSurfaceRef.
func (*ANESurface) NFrames ¶
func (a *ANESurface) NFrames() uint64
NFrames returns the number of allocated multi-buffer frames.
func (*ANESurface) PixelFormat ¶
func (a *ANESurface) PixelFormat() uint32
PixelFormat returns the surface pixel format.
func (*ANESurface) ReadFrame ¶
func (a *ANESurface) ReadFrame(_ uint64, _ []byte) error
ReadFrame reads raw bytes from the IOSurface backing the given frame.
func (*ANESurface) ReadFrameF32 ¶
func (a *ANESurface) ReadFrameF32(_ uint64, _ []float32) error
ReadFrameF32 reads float32 data from the IOSurface backing the given frame.
func (*ANESurface) ResizeForAsync ¶
func (a *ANESurface) ResizeForAsync(_ uint64)
ResizeForAsync resizes the surface for multiple async buffer frames.
func (*ANESurface) RestoreAllInternalStorage ¶
func (a *ANESurface) RestoreAllInternalStorage()
RestoreAllInternalStorage restores internal storage for all multi-buffer frames.
func (*ANESurface) RestoreInternalStorage ¶
func (a *ANESurface) RestoreInternalStorage(_ uint64)
RestoreInternalStorage restores internal storage for a single slot.
func (*ANESurface) SetAliasingMem ¶
func (a *ANESurface) SetAliasingMem(_ any)
SetAliasingMem sets the external storage blob for aliasing memory.
func (*ANESurface) SetExternalStorage ¶
func (a *ANESurface) SetExternalStorage(_ uint64, _ uintptr)
SetExternalStorage replaces the IOSurface backing a storage slot.
func (*ANESurface) WriteFrame ¶
func (a *ANESurface) WriteFrame(_ uint64, _ []byte) error
WriteFrame writes raw bytes to the IOSurface backing the given frame.
func (*ANESurface) WriteFrameF32 ¶
func (a *ANESurface) WriteFrameF32(_ uint64, _ []float32) error
WriteFrameF32 writes float32 data to the IOSurface backing the given frame.
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder constructs Espresso IR JSON (model.espresso.net + model.espresso.shape) and optional weight binaries for inference on Apple's Espresso framework.
func NewBuilder ¶
func NewBuilder() *Builder
NewBuilder creates a new Espresso IR builder with format version 200.
func (*Builder) Activation ¶
func (b *Builder) Activation(name, mode string, opts ...LayerOption) *Builder
Activation adds an activation layer.
func (*Builder) BatchNorm ¶
func (b *Builder) BatchNorm(name string, channels int, opts ...LayerOption) *Builder
BatchNorm adds a batch normalization layer.
func (*Builder) BuildWithWeights ¶
BuildWithWeights produces IR JSON and a weight binary.
func (*Builder) Concat ¶
func (b *Builder) Concat(name string, opts ...LayerOption) *Builder
Concat adds a concatenation layer.
func (*Builder) Convolution ¶
func (b *Builder) Convolution(name string, nOutput, kernelH, kernelW int, opts ...LayerOption) *Builder
Convolution adds a convolution layer.
func (*Builder) Elementwise ¶
func (b *Builder) Elementwise(name, operation string, opts ...LayerOption) *Builder
Elementwise adds an elementwise operation layer with a string operation name.
func (*Builder) ElementwiseOped ¶
func (b *Builder) ElementwiseOped(name string, op ElementwiseOp, opts ...LayerOption) *Builder
ElementwiseOped adds an elementwise operation layer with a typed operation code.
func (*Builder) InnerProduct ¶
func (b *Builder) InnerProduct(name string, nOutput int, opts ...LayerOption) *Builder
InnerProduct adds a fully connected layer.
func (*Builder) Pooling ¶
func (b *Builder) Pooling(name, mode string, kernelH, kernelW int, opts ...LayerOption) *Builder
Pooling adds a pooling layer.
type Context ¶
type Context struct{}
Context manages execution state for Espresso networks.
func Open ¶
func Open(_ ...ContextOption) (*Context, error)
Open creates a new Espresso execution context.
func (*Context) LoadNetwork ¶
func (c *Context) LoadNetwork(_ []byte, _ ...NetworkOption) (*Network, error)
LoadNetwork loads a network from Espresso IR.
func (*Context) LoadNetworkFromFile ¶
func (c *Context) LoadNetworkFromFile(_ string, _ ...NetworkOption) (*Network, error)
LoadNetworkFromFile loads a network from an Espresso net.json file.
type ContextOption ¶
type ContextOption func(*contextConfig)
ContextOption configures a Context.
func WithGPUPriority ¶
func WithGPUPriority(_ uint32) ContextOption
WithGPUPriority sets the GPU command buffer priority.
func WithLowPriority ¶
func WithLowPriority(_ float32) ContextOption
WithLowPriority sets the max ms per command buffer for low priority.
func WithPlatform ¶
func WithPlatform(_ Platform) ContextOption
WithPlatform selects the execution backend.
type ElementwiseOp ¶
type ElementwiseOp int
ElementwiseOp identifies an Espresso elementwise operation by its numeric code.
const ( ElementwiseAdd ElementwiseOp = 0 ElementwiseMul ElementwiseOp = 1 ElementwiseMax ElementwiseOp = 2 ElementwiseMin ElementwiseOp = 3 ElementwiseSub ElementwiseOp = 5 ElementwiseDiv ElementwiseOp = 6 ElementwiseSqrt ElementwiseOp = 10 ElementwiseExp ElementwiseOp = 11 ElementwiseRsqrt ElementwiseOp = 12 ElementwiseLog ElementwiseOp = 13 ElementwisePow ElementwiseOp = 14 ElementwiseAbs ElementwiseOp = 15 )
Espresso elementwise operation codes.
type EvalOptions ¶
EvalOptions configures execution behavior.
type Frame ¶
type Frame struct{}
Frame holds named input and output tensors for network execution.
func (*Frame) FunctionName ¶
FunctionName returns the function name set on this frame.
func (*Frame) InputNames ¶
InputNames returns the names of all input attachments.
func (*Frame) OutputFloat64 ¶
OutputFloat64 returns the named output as float64 values.
func (*Frame) OutputInto ¶
OutputInto copies the named output tensor data into the caller's buffer.
func (*Frame) OutputNames ¶
OutputNames returns the names of all output attachments.
func (*Frame) SetFunctionName ¶
SetFunctionName sets the function name.
func (*Frame) SetGroundTruth ¶
SetGroundTruth attaches a named ground truth tensor.
func (*Frame) SetInputBytes ¶
SetInputBytes attaches a named raw byte input.
func (*Frame) SetInputCVPixelBuffer ¶
SetInputCVPixelBuffer attaches a named input from a CVPixelBuffer.
func (*Frame) SetInputIOSurface ¶
SetInputIOSurface attaches a named input backed by an IOSurface.
type FrameStorage ¶
type FrameStorage struct{}
FrameStorage holds reusable multi-frame storage.
func NewFrameStorage ¶
func NewFrameStorage(_ ...*Frame) *FrameStorage
NewFrameStorage creates reusable storage from the given frames.
type LayerOption ¶
type LayerOption func(*layerDef)
LayerOption configures a layer definition.
func WithBias ¶
func WithBias(data []float32) LayerOption
WithBias assigns float32 bias data to a layer.
func WithBottom ¶
func WithBottom(names ...string) LayerOption
WithBottom sets the input blob names for a layer.
func WithHasReLU ¶
func WithHasReLU(v bool) LayerOption
WithHasReLU enables fused ReLU on the layer.
func WithPad ¶
func WithPad(t, b, l, r int) LayerOption
WithPad sets padding [top, bottom, left, right].
func WithTop ¶
func WithTop(names ...string) LayerOption
WithTop sets the output blob names for a layer.
func WithWeights ¶
func WithWeights(data []float32) LayerOption
WithWeights assigns float32 weight data to a layer.
type LayerProfile ¶
type LayerProfile struct {
Name string
DebugName string
AvgRuntimeMS float64
RuntimeSamples []float64
Engine Engine
Supported bool
HasPerfWarning bool
LayerType string
}
LayerProfile contains profiling data for a single layer.
func (*LayerProfile) IsANEResident ¶
func (l *LayerProfile) IsANEResident() bool
IsANEResident reports whether this layer runs on the ANE.
type LayerShape ¶
type LayerShape struct {
Name string // blob name
N int // batch
C int // channels
H int // height
W int // width
}
LayerShape describes the tensor shape for a layer blob as parsed from model.espresso.shape JSON.
func (LayerShape) Elements ¶
func (s LayerShape) Elements() int
Elements returns the total number of elements in this shape.
type MetalDevice ¶
type MetalDevice struct{}
MetalDevice wraps a Metal GPU device for zero-copy interop with Espresso.
func OpenMetal ¶
func OpenMetal() (*MetalDevice, error)
OpenMetal opens the system default Metal device.
type Network ¶
type Network struct {
// contains filtered or unexported fields
}
Network is a loaded Espresso neural network ready for execution.
func (*Network) EvalAsyncWithCallback ¶
EvalAsyncWithCallback executes the network asynchronously with a callback.
func (*Network) EvalWithOptions ¶
func (n *Network) EvalWithOptions(_ *Frame, _ EvalOptions) error
EvalWithOptions executes with custom options.
func (*Network) EvalWithStorage ¶
func (n *Network) EvalWithStorage(_ *FrameStorage, _ EvalOptions) error
EvalWithStorage executes the network using pre-allocated storage.
func (*Network) HasLayer ¶
HasLayer reports whether the network contains a layer with the given name.
func (*Network) LayerCount ¶
LayerCount returns the number of layers.
func (*Network) LayerNames ¶
LayerNames returns the names of all layers.
type NetworkOption ¶
type NetworkOption func(*networkConfig)
NetworkOption configures network loading.
func WithBinSerializerID ¶
func WithBinSerializerID(_ []byte) NetworkOption
WithBinSerializerID sets the binary serializer ID.
func WithComputePath ¶
func WithComputePath(_ int) NetworkOption
WithComputePath sets the compute path.
type Pass ¶
type Pass interface {
// Name returns the pass identifier.
Name() string
// Run applies the optimization to the network. Returns true if modified.
Run(n *Network) bool
}
Pass is a network optimization pass that transforms an Espresso network.
type Profile ¶
type Profile struct {
Path string
Layers []LayerProfile
ANE *ANEProfile
}
Profile contains execution profiling data for a network.
func ProfileNetwork ¶
ProfileNetwork extracts profiling data from a loaded network.
func (*Profile) ANEResidentLayers ¶
func (p *Profile) ANEResidentLayers() []LayerProfile
ANEResidentLayers returns layers that are resident on the ANE.
func (*Profile) CPUFallbackLayers ¶
func (p *Profile) CPUFallbackLayers() []LayerProfile
CPUFallbackLayers returns supported layers that fell back to CPU instead of ANE.
func (*Profile) IsFullyANEResident ¶
IsFullyANEResident reports whether all supported layers run on the ANE.
func (*Profile) LayersByEngine ¶
func (p *Profile) LayersByEngine() map[Engine][]LayerProfile
LayersByEngine returns layers grouped by their execution engine.
func (*Profile) TotalRuntimeMS ¶
TotalRuntimeMS returns the sum of average runtimes across all layers.
func (*Profile) UnsupportedLayers ¶
func (p *Profile) UnsupportedLayers() []LayerProfile
UnsupportedLayers returns layers that are not supported by the main engine.
type Shape ¶
type Shape struct {
Batch int
Channels int
Height int
Width int
Sequence int // for RNN/transformer models
}
Shape describes tensor dimensions.
type ShapeMap ¶
type ShapeMap struct {
Shapes map[string]LayerShape
}
ShapeMap holds parsed shape information for all blobs in a model.
func ReadEspressoShape ¶
ReadEspressoShape parses a model.espresso.shape JSON file into a ShapeMap.
The shape JSON has the structure:
{
"layer_shapes": {
"blob_name": { "n": 1, "k": 64, "h": 1, "w": 128 },
...
}
}
where k=channels, h=height, w=width, n=batch.
func ReadEspressoShapeFile ¶
ReadEspressoShapeFile reads and parses a model.espresso.shape JSON file.