Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/articles_en/assets/snippets/AUTO0.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
// Copyright (C) 2018-2026 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

//! [py_ov_property_import_header]
#include <openvino/openvino.hpp>
#include <openvino/runtime/auto/properties.hpp>
//! [py_ov_property_import_header]

int main() {
Expand All @@ -25,6 +30,17 @@ ov::CompiledModel model4 = core.compile_model(model, "AUTO", ov::device::priorit
// the AUTO plugin is pre-configured (globally) with the explicit option:
core.set_property("AUTO", ov::device::priorities("GPU,CPU"));
//! [part0]
}
{
//! [compile_for_all]
ov::Core core;
auto model = core.read_model("model.xml");
auto compiled_model = core.compile_model(model,
"AUTO",
ov::device::priorities("GPU,CPU"),
ov::cache_dir("model_cache"),
ov::intel_auto::compile_for_all(true));
//! [compile_for_all]
}
return 0;
}
19 changes: 19 additions & 0 deletions docs/articles_en/assets/snippets/ov_auto.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# SPDX-License-Identifier: Apache-2.0
#

import tempfile

#! [py_ov_property_import_header]
import openvino as ov
import openvino.properties as properties
Expand Down Expand Up @@ -181,6 +183,22 @@ def part7():
#! [part7]


def part8():
with tempfile.TemporaryDirectory() as cache_dir:
#! [compile_for_all]
core = ov.Core()
compiled_model = core.compile_model(
model=model,
device_name="AUTO",
config={
device.priorities: "GPU,CPU",
properties.cache_dir: cache_dir,
intel_auto.compile_for_all: True,
},
)
#! [compile_for_all]


def main():
part3()
part4()
Expand All @@ -192,3 +210,4 @@ def main():
return 0
part0()
part1()
part8()
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ What is important, **AUTO starts inference with the CPU of the system by default
While the CPU is performing inference, AUTO continues to load the model to the device best suited for the purpose and transfers the task to it when ready.
This way, the devices which are much slower in compiling models, GPU being the best example, do not impact inference at its initial stages.
For example, if you use a CPU and a GPU, the first-inference latency of AUTO will be better than that of using GPU alone.
See :ref:`Pre-compiling the Model for Other Devices <auto-compile-for-all>` for the cache warm-up option and its latency and fallback trade-offs.

Note that if you choose to exclude CPU from the priority list or disable the initial
CPU acceleration feature via ``ov::intel_auto::enable_startup_fallback``, it will be
Expand Down Expand Up @@ -169,9 +170,6 @@ the following setup options:
| | Enables/disables CPU as acceleration (or the helper device) in the |
| | beginning. The default value is ``true``, indicating that CPU is |
| | used as acceleration by default. |
| | |
| | As a trade-off, two model instances will be kept, resulting in |
| | additional memory usage of approximately one model’s size. |
+----------------------------------------------+--------------------------------------------------------------------+
| ``ov::intel_auto::enable_runtime_fallback`` | **Values**: |
| | |
Expand Down Expand Up @@ -202,35 +200,10 @@ the following setup options:
| | |
| | ``false`` |
| | |
| | Compiles the model to the remaining candidate devices in the |
| | background, after the actual device is ready, to populate cache |
| | blobs for faster device switching later. Devices whose cache blob |
| | already exists are skipped. CPU candidates are excluded from |
| | background pre-compilation. |
| | |
| | Enabling it disables ``ov::intel_auto::enable_startup_fallback`` |
| | and ``ov::intel_auto::enable_runtime_fallback``. |
| | |
| | Requires ``ov::cache_dir`` or ``ov::cache_path``. Without them, |
| | compiling the model throws on every host. |
| | |
| | Ignored in cumulative throughput mode, when there is no |
| | other candidate device to compile, and when ``ov::cache_blob_id`` |
| | is set for AUTO or for any candidate device. |
| | |
| | A device whose cache path is a single-file cache (``*.bin``) is |
| | skipped with a warning. |
| | |
| | Only the devices listed in ``ov::device::priorities`` or in the |
| | device string, for example ``AUTO:GPU,NPU``, are compiled; other |
| | available devices are not. With ``AUTO:GPU,NPU``, if GPU becomes |
| | actual device, NPU is compiled in the background (and vice versa). |
| | |
| | Warm-up compiles one device at a time and releases each compiled |
| | model right away. The memory needed by the background compilation |
| | itself is not included. |
| | |
| | The default value is ``false``. |
| | Enables background cache warm-up for other eligible candidates. |
| | Default: ``false``. Disables startup/runtime fallbacks if active. |
| | First-inference latency may increase. |
| | See :ref:`details <auto-compile-for-all>`. |
+----------------------------------------------+--------------------------------------------------------------------+

Inference with AUTO is configured similarly to when device plugins are used:
Expand All @@ -256,6 +229,52 @@ The code samples on this page assume following import(Python)/using (C++) are in



.. _auto-compile-for-all:

Pre-compiling the Model for Other Devices
+++++++++++++++++++++++++++++++++++++++++

Enable ``ov::intel_auto::compile_for_all`` to prepare cached models for other eligible devices, including CPU,
in the background after the execution device is ready. This can speed up later ``compile_model`` calls;
it does not change the current execution device. Candidates come from ``ov::device::priorities`` or the device
string; plain ``AUTO`` uses its usual eligible devices.

* Requires ``ov::cache_dir`` or ``ov::cache_path``. Without either, ``compile_model`` throws unless the property
is ignored in cumulative throughput mode or because ``ov::cache_blob_id`` is set for AUTO or any candidate.
* Ignored in ``CUMULATIVE_THROUGHPUT`` mode, with ``ov::cache_blob_id``, or when no other candidate exists at
scheduling initialization. In the last case, cache settings are validated first and fallbacks remain unchanged.
* When active, disables ``ov::intel_auto::enable_startup_fallback`` and ``ov::intel_auto::enable_runtime_fallback``
at initialization, even if startup retries later remove all warm-up candidates. This may increase first-inference
latency and prevents retrying a failed inference on another device.
* Skips devices with caching disabled or a single-file cache path (``*.bin``). Warm-up failures are logged as warnings.
Core reuses compatible cache blobs and may rebuild invalid ones.

Warm-up compiles one device at a time and releases each temporary compiled model. Background compilation adds

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding background compilation overhead and resource usage:
When warming up GPU, make_warmup_config configures ov::intel_gpu::hint::host_task_priority(ov::hint::Priority::LOW). However, the CPU plugin does not support host_task_priority or compilation_num_threads. As a result, background warm-up on CPU runs with full TBB thread concurrency, competing for host CPU cores and memory bandwidth with active inference on the primary execution device.

It would be helpful to explicitly mention in this section that background CPU warm-up can cause host CPU and memory contention during ongoing inference (or consider applying a reduced-stream / lower-thread configuration in make_warmup_config for CPU, since CPU cache key generation depends only on full_name).

memory overhead, including a private clone for in-memory models. Destroying the AUTO compiled model cancels pending
warm-ups and waits for any compilation already in progress.

GPU warm-up runs with low host task priority, but the CPU plugin has no equivalent setting. A background CPU warm-up
therefore competes with ongoing inference for host CPU cores and memory bandwidth.

See :doc:`Model Caching Overview <../optimize-inference/optimizing-latency/model-caching-overview>` for cache settings.

.. tab-set::

.. tab-item:: Python
:sync: py

.. doxygensnippet:: docs/articles_en/assets/snippets/ov_auto.py
:language: python
:fragment: [compile_for_all]

.. tab-item:: C++
:sync: cpp

.. doxygensnippet:: docs/articles_en/assets/snippets/AUTO0.cpp
:language: cpp
:fragment: [compile_for_all]


Device Candidates and Priority
++++++++++++++++++++++++++++++

Expand Down
1 change: 1 addition & 0 deletions src/bindings/c/docs/api_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ OPENVINO_C_VAR(const char*) ov_property_key_intel_auto_device_bind_buffer;
OPENVINO_C_VAR(const char*) ov_property_key_intel_auto_enable_startup_fallback;

OPENVINO_C_VAR(const char*) ov_property_key_intel_auto_enable_runtime_fallback;

OPENVINO_C_VAR(const char*) ov_property_key_intel_auto_compile_for_all;
```

Expand Down
6 changes: 4 additions & 2 deletions src/bindings/c/include/openvino/c/auto/properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ OPENVINO_C_VAR(const char*)
ov_property_key_intel_auto_enable_runtime_fallback;

/**
* @brief Read-write property<string> to enable/disable compiling the model to all candidate devices in the
* background to populate cache blobs for faster subsequent loading (requires ov::cache_dir or ov::cache_path)
* @brief Boolean property to enable background cache warm-up for other eligible AUTO candidate devices.
* In the C API, pass the string value "YES" or "NO". Requires ov::cache_dir or ov::cache_path; the property is
* ignored in cumulative throughput mode or when ov::cache_blob_id is set. When active, startup and runtime fallbacks
* are disabled for this compile.
* @ingroup ov_property_c_api
*/
OPENVINO_C_VAR(const char*)
Expand Down
20 changes: 10 additions & 10 deletions src/inference/include/openvino/runtime/auto/properties.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,20 @@ static constexpr Property<bool> enable_startup_fallback{"ENABLE_STARTUP_FALLBACK
static constexpr Property<bool> enable_runtime_fallback{"ENABLE_RUNTIME_FALLBACK"};

/**
* @brief auto device setting that enables compiling the model to the remaining candidate devices in the background,
* after the actual device is ready, to populate cache blobs for faster device switching.
* Enabling it disables ov::intel_auto::enable_startup_fallback and ov::intel_auto::enable_runtime_fallback.
* Requires ov::cache_dir or ov::cache_path, otherwise compiling the model throws on every host. Ignored in
* cumulative throughput mode, when there is no other candidate device, and when
* ov::cache_blob_id is set. Devices are skipped when the cache path is a single-file cache (*.bin).
* @brief Enables background cache warm-up for AUTO candidate devices other than the one AUTO serves inference on,
* including CPU when it is a candidate. Warm-up fills the model cache for a later compile_model call; it does not
* switch the current compiled model to another device.
*
* When ov::device::priorities (or a device string such as "AUTO:GPU,NPU") is set, it determines the candidates;
* otherwise AUTO discovers its usual eligible devices. For example, to warm up the cache for GPU and NPU, so that
* the one not selected by AUTO is compiled in the background:
* Requires ov::cache_dir or ov::cache_path; compiling the model throws otherwise. The property is ignored in
* cumulative throughput mode, when ov::cache_blob_id is set, or when no other candidate exists. When active, it
* disables ov::intel_auto::enable_startup_fallback and ov::intel_auto::enable_runtime_fallback for this compile.
* Warm-up failures are logged as warnings. See the AUTO device selection article for details.
*
* For example, to warm up other eligible candidates:
* @code
* core.compile_model(model,
* "AUTO",
* ov::device::priorities("GPU,NPU"),
* ov::device::priorities("GPU,CPU"),
* ov::cache_dir("model_cache"),
* ov::intel_auto::compile_for_all(true));
* @endcode
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/auto/src/auto_schedule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,10 @@ void AutoSchedule::init() {
const auto& actual_device = m_compile_context[ACTUALDEVICE].m_device_info.device_name;
const auto& candidates = m_compile_context[ACTUALDEVICE].m_meta_devices;
const bool has_warmup_candidate = std::any_of(candidates.begin(), candidates.end(), [&](const auto& device) {
return device.device_name != actual_device && ov::DeviceIDParser(device.device_name).get_device_name() != "CPU";
return device.device_name != actual_device;
});
if (!has_warmup_candidate) {
LOG_WARNING_TAG("compile_for_all is ignored: no other non-CPU candidate device to compile");
LOG_WARNING_TAG("compile_for_all is ignored: no other candidate device to compile");
m_context->m_compile_for_all = false;
} else {
// Fallbacks switch devices non-deterministically and would overlap with the background warm-up.
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/auto/src/cache_warmup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ const std::string& CacheWarmup::get_log_tag() const noexcept {
void CacheWarmup::start(const std::string& actual_device, const std::vector<DeviceInformation>& candidates) {
std::vector<DeviceInformation> devices;
for (const auto& device : candidates) {
if (device.device_name != actual_device && ov::DeviceIDParser(device.device_name).get_device_name() != "CPU") {
if (device.device_name != actual_device) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that CPU candidates are included in background cache warm-up (removing the previous CPU exclusion here and in AutoSchedule), please note that the class documentation in src/plugins/auto/src/cache_warmup.hpp (line 22) still says:

//  1. start() is called once the actual device is known. It filters out the actual device and CPU, then hands this
//     object to CacheWarmupManager (once per object).

Please update cache_warmup.hpp to remove "and CPU" so that the header comments remain consistent with this change.

devices.push_back(device);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/auto/src/cache_warmup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ class CacheWarmupManager;
// exist the next time the model is loaded (e.g. when a different device is picked later). Needs a cache dir/path.
//
// Flow:
// 1. start() is called once the actual device is known. It filters out the actual device and CPU, then hands this
// object to CacheWarmupManager (once per object).
// 1. start() is called once the actual device is known. It filters out the actual device, then hands this object
// to CacheWarmupManager (once per object).
// 2. The manager's single worker thread calls run(), which handles the devices one by one:
// - caching disabled for the device (no cache dir/path) -> skip;
// - the blob for this model/config is already in the cache -> skip;
Expand Down
8 changes: 0 additions & 8 deletions src/plugins/auto/src/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,11 +636,6 @@ std::shared_ptr<ov::ICompiledModel> Plugin::compile_model_impl(const std::filesy
auto_s_context->m_model_precision = model_precision;
auto_s_context->m_compile_for_all = load_config.get_property(ov::intel_auto::compile_for_all);
if (auto_s_context->m_compile_for_all) {
std::vector<const DeviceInformation*> warmup_candidates;
for (const auto& device : auto_s_context->m_device_priorities_initial) {
if (ov::DeviceIDParser(device.device_name).get_device_name() != "CPU")
warmup_candidates.push_back(&device);
}
// A user blob ID does not identify a device, so blobs warmed up for other devices would overwrite each other.
const bool has_blob_id =
full_property.count(ov::cache_blob_id.name()) != 0 ||
Expand All @@ -663,9 +658,6 @@ std::shared_ptr<ov::ICompiledModel> Plugin::compile_model_impl(const std::filesy
})) {
// Independent of how many devices the host has, so the contract of an explicit true is the same everywhere.
OPENVINO_THROW(ov::intel_auto::compile_for_all.name(), " requires ov::cache_dir or ov::cache_path to be set");
} else if (warmup_candidates.empty() || auto_s_context->m_device_priorities_initial.size() < 2) {
LOG_WARNING_TAG("compile_for_all is ignored: no other candidate device to compile");
auto_s_context->m_compile_for_all = false;
}
}
auto_s_context->m_schedule_policy = load_config.get_property(ov::intel_auto::schedule_policy);
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/auto/src/utils/log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
namespace ov {
namespace auto_plugin {
ov::log::Level Log::default_log_level = ov::log::Level::NO;
std::vector<std::string> Log::valid_format = {"u", "d", "s", "ld", "lu", "lf"};
std::vector<std::string> Log::valid_format = {"u", "d", "s", "ld", "lu", "lf", "zu"};
} // namespace auto_plugin
} // namespace ov
Loading
Loading