Skip to content

OpenVINO Backend API

OpenVINOBackend

torch_tweak.torch.backend.OpenVINOBackend

OpenVINOBackend(config=None)

Bases: Backend

Runs inference via OpenVINO compiled models (Intel CPU/GPU).

Initializes backend.

Source code in torch_tweak/torch/backend/openvino/openvino_backend.py
def __init__(self, config: OpenVINOBackendConfig | None = None):
    """Initializes backend."""
    super().__init__()
    self._config = config or OpenVINOBackendConfig()
    self._ov_model_dir: Path | None = None
    self._ov_model_xml: Path | None = None
    self._graph_spec: GraphSpec | None = None
    self._output_object: Any = None
    self._compiled_model: ov.CompiledModel | None = None

device property

device

The device of the backend.

Returns:

  • device –

    The device the module is using.

is_active property

is_active

True if the backend is active.

name property

name

Name of a backend.

activate

activate()

Activates backend.

After activating, the backend should be ready to do inference.

Source code in torch_tweak/torch/backend/backend.py
@annotate(domain="Torch Tweak")
def activate(self):
    """Activates backend.

    After activating, the backend should be ready to do inference.
    """
    if self.state == BackendState.INIT:
        raise RuntimeError(f"Cannot activate backend {self.name}, backend should be built first")
    if self.state == BackendState.DEPLOYED:
        raise RuntimeError(f"Cannot activate backend {self.name}, backend is already deployed")

    if self.state == BackendState.INACTIVE or self.state == BackendState.CHECKPOINT_LOADED:
        self._activate()
        self.state = BackendState.ACTIVE

build

build(module, graph_spec, data, device, cache_dir)

Build the model with the given arguments.

Building a backend should be idempotent i.e. do not cause side effects. A model is not necessarily pure functional and can have an internal state (like kv cache for LLMs). That is why build can call a sample of inputs at most once so that subsequent calls have exact same state as the first call for the given sample.

After building, the backend should be activated.

Source code in torch_tweak/torch/backend/backend.py
def build(
    self,
    module: nn.Module,
    graph_spec: GraphSpec,
    data: list[Sample],
    device: torch.device,
    cache_dir: Path,
) -> "Backend":
    """Build the model with the given arguments.

    Building a backend should be idempotent i.e. do not cause side effects. A model is not necessarily pure
    functional and can have an internal state (like kv cache for LLMs). That is why build can call a sample of
    inputs at most once so that subsequent calls have exact same state as the first call for the given sample.

    After building, the backend should be activated.
    """
    if self.state == BackendState.INIT:
        try:
            self._assert_device(device)
            self._set_device(device)
            ready_backend = self._build(module, graph_spec, data, cache_dir)
            self.state = BackendState.ACTIVE
            return ready_backend
        except Exception as e:
            self._logger.error("Failed to build backend(%s): %s", self.__class__.__name__, e, exc_info=True)
            raise e
    else:
        raise RuntimeError(f"Backend {self.name} build should be called only once")

deactivate

deactivate()

Deactivates backend.

After deactivating, the backend cannot be used to do inference.

Source code in torch_tweak/torch/backend/backend.py
def deactivate(self):
    """Deactivates backend.

    After deactivating, the backend cannot be used to do inference.
    """
    if self.state == BackendState.INIT:
        raise RuntimeError(f"Cannot deactivate backend {self.name}, backend should be built first")
    if self.state == BackendState.DEPLOYED:
        raise RuntimeError(f"Cannot deactivate backend {self.name}, backend is already deployed")
    if self.state == BackendState.CHECKPOINT_LOADED:
        raise RuntimeError(f"Cannot deactivate backend {self.name}, backend has already been deployed")

    if self.state == BackendState.ACTIVE:
        self._deactivate()
        self._clean_memory()
        self.state = BackendState.INACTIVE

deploy

deploy(device)

Deploys the backend.

After deploying, the backend is ready to do inference. Backend cannot be deactivated anymore.

Parameters:

  • device (device | None) –

    The device to deploy the backend on.

Source code in torch_tweak/torch/backend/backend.py
def deploy(self, device: torch.device | None):
    """Deploys the backend.

    After deploying, the backend is ready to do inference. Backend cannot be deactivated anymore.

    Args:
        device: The device to deploy the backend on.
    """
    if self.state != BackendState.CHECKPOINT_LOADED:
        raise RuntimeError(f"Cannot deploy backend {self.name}, backend should be loaded from a checkpoint")

    self._set_device(device)
    self._deploy()
    self.state = BackendState.DEPLOYED

describe

describe()

Returns the description of the backend.

Source code in torch_tweak/torch/backend/openvino/openvino_backend.py
def describe(self) -> str:
    """Returns the description of the backend."""
    return f"{self.__class__.__name__}({self._config.describe()})"

from_dict classmethod

from_dict(module, state_dict)

Creates a backend from a state_dict.

Source code in torch_tweak/torch/backend/openvino/openvino_backend.py
@classmethod
def from_dict(cls, module: torch.nn.Module | None, state_dict: dict):
    """Creates a backend from a state_dict."""
    if state_dict.get(cls.STATE_TYPE) != cls.__name__:
        raise ValueError(f"Invalid state_dict type: {state_dict.get(cls.STATE_TYPE)}")

    config = OpenVINOBackendConfig.from_dict(state_dict[cls.STATE_CONFIG])
    backend = cls(config=config)
    if cls.STATE_OV_MODEL_DIR not in state_dict:
        raise ValueError("Checkpoint is missing OpenVINO model path (ov_model_dir).")
    backend._ov_model_dir = Path(state_dict[cls.STATE_OV_MODEL_DIR])
    backend._ov_model_xml = backend._ov_model_dir / OV_MODEL_XML_NAME
    backend._output_object = state_dict[cls.STATE_OUTPUT_OBJECT]
    backend._graph_spec = GraphSpec.from_dict(state_dict[cls.STATE_GRAPH_SPEC])
    backend._set_device(state_dict[cls.STATE_DEVICE])
    backend.state = BackendState.CHECKPOINT_LOADED
    return backend

infer

infer(*args, **kwargs)

Run inference with the given arguments.

Parameters:

  • args (Any, default: () ) –

    Variable length argument list.

  • kwargs (Any, default: {} ) –

    Arbitrary keyword arguments.

Returns:

  • Any ( Any ) –

    The result of the inference.

Source code in torch_tweak/torch/backend/backend.py
def infer(self, *args: Any, **kwargs: Any) -> Any:
    """Run inference with the given arguments.

    Args:
        args: Variable length argument list.
        kwargs: Arbitrary keyword arguments.

    Returns:
        Any: The result of the inference.
    """
    if self.state != BackendState.ACTIVE and self.state != BackendState.DEPLOYED:
        raise RuntimeError(f"Cannot run inference, backend {self.name} should be activated first")

    return self._infer(*args, **kwargs)

key

key()

Returns the key of the backend.

Source code in torch_tweak/torch/backend/openvino/openvino_backend.py
def key(self) -> str:
    """Returns the key of the backend."""
    return f"{self.__class__.__name__}_{self._config.key()}"

to_dict

to_dict()

Returns the state_dict of the backend.

Source code in torch_tweak/torch/backend/openvino/openvino_backend.py
def to_dict(self):
    """Returns the state_dict of the backend."""
    if self._ov_model_dir is None or self._graph_spec is None:
        raise RuntimeError("Backend has not been properly initialized. Please call build() first.")
    return {
        self.STATE_TYPE: self.__class__.__name__,
        self.STATE_CONFIG: self._config.to_dict(),
        self.STATE_OV_MODEL_DIR: self._ov_model_dir,
        self.STATE_OUTPUT_OBJECT: self._output_object,
        self.STATE_GRAPH_SPEC: self._graph_spec.to_dict(),
        self.STATE_DEVICE: self._device,
    }

OpenVINOBackendConfig

torch_tweak.torch.backend.OpenVINOBackendConfig dataclass

OpenVINOBackendConfig(use_dynamo=True, performance_hint='LATENCY')

Bases: BackendConfig

Configuration for OpenVINO backend.

Attributes:

  • use_dynamo (bool) –

    Use torch.export (True) or legacy trace conversion (False) in OVC.

  • performance_hint (str) –

    OpenVINO compile hint (LATENCY, THROUGHPUT, CUMULATIVE_THROUGHPUT).

describe

describe()

Describe the backend configuration. Display only changed fields.

Source code in torch_tweak/torch/backend/backend.py
def describe(self) -> str:
    """Describe the backend configuration. Display only changed fields."""
    default = self.__class__()
    changed_fields = self._get_changed_fields(self, default)
    return ",".join(changed_fields)

from_dict classmethod

from_dict(state_dict)

Convert dict to OpenVINOBackendConfig.

Source code in torch_tweak/torch/backend/openvino/openvino_backend.py
@classmethod
def from_dict(cls, state_dict: dict):
    """Convert dict to OpenVINOBackendConfig."""
    return cls(**state_dict)

key

key()

Returns the keys of the backend configuration.

Source code in torch_tweak/torch/backend/backend.py
def key(self) -> str:
    """Returns the keys of the backend configuration."""
    config_dict = self.to_dict()
    config_dict = self._to_json(config_dict)
    config_dict_str = json.dumps(config_dict)
    key = hash_string(config_dict_str)
    return key

to_dict

to_dict()

Returns the state_dict of the backend.

Source code in torch_tweak/torch/backend/backend.py
def to_dict(self):
    """Returns the state_dict of the backend."""
    return asdict(self)

to_json

to_json(path)

Saves the backend configuration to a file.

Source code in torch_tweak/torch/backend/backend.py
def to_json(self, path: Path):
    """Saves the backend configuration to a file."""
    config_dict = self.to_dict()
    config_dict = self._to_json(config_dict)
    with open(path, "w", encoding="utf-8") as f:
        json.dump(config_dict, f, indent=2)
    secure_file(path)