高级别性能提示

OpenVINO 的每一个支持的设备都提供低级别性能设置。调整这种详细的配置需要深入理解架构。此外,尽管对特定的设备和推理模型组合而言性能可能最优,但所得配置对其他设备或模型而言并不一定是最优的。OpenVINO 性能提示是在考虑可移植性的情况下配置性能的新方法。

这些提示还会以正确的方式“倒转”配置方向:其思路不是将应用需求映射到低级别性能设置,并保持相关的应用逻辑来单独配置每个可能的设备,而是用单个配置键来表达目标场景,并让设备对自身进行配置作为响应。由于每个 OpenVINO 设备都支持这些提示,因此,这是一个完全可移植、永不落伍的解决方案,并且与自动设备选择完全兼容。

以前,一定级别的自动配置来自参数的默认值。例如,在设置 ov::streams::AUTO(在 OpenVINO 2.0 之前叫作 CPU_THROUGHPUT_AUTO)时,CPU 流的数量是从 CPU 核心数量推导出来的。然而,得到的流的数量并没有考虑要推理的模型的实际计算需求。相反,这些提示会考虑实际模型,因此会针对每个型号单独计算最佳吞吐量的参数(基于计算与内存带宽要求和设备的功能)。

性能提示:延迟和吞吐量

优化指南中所论,有一些不同的指标与推理速度相关联。吞吐量和延迟是衡量整体性能使用的最广泛的应用指标。

这就是为什么为了简化设备的配置,OpenVINO 提供了两个专用提示,即 ov::hint::PerformanceMode::THROUGHPUTov::hint::PerformanceMode::LATENCY。一个特殊的 ov::hint::PerformanceMode::UNDEFINED,其作用等同于不指定任何提示。

另请参见本文档最后一节有关使用 benchmark_app 进行性能测量的内容。

请注意,与 ov::hint::PerformanceMode::LATENCY 相比,典型模型在 ov::hint::PerformanceMode::THROUGHPUT 下的加载时间可能要长得多,并且消耗更多的内存。

性能提示:原理

在内部,每个设备都把提示的值“转换”成实际性能设置。例如,ov::hint::PerformanceMode::THROUGHPUT 选择 CPU 或 GPU 流的数量。对于 GPU,另外还会选择最佳的批处理大小,并尽可能地应用自动批处理(如果设备支持,也可以参考设备/功能支持表)。

所得到的(设备特定的)设置可以从 ov:Compiled_Model 的实例中查询。

请注意,benchmark_app 输出的是吞吐量提示的实际设置,请参见下面的输出示例:

$benchmark_app -hint tput -d CPU -m 'path to your favorite model'
...
[Step 8/11] Setting optimal runtime parameters
[ INFO ] Device: CPU
[ INFO ]   { PERFORMANCE_HINT , THROUGHPUT }
...
[ INFO ]   { OPTIMAL_NUMBER_OF_INFER_REQUESTS , 4 }
[ INFO ]   { NUM_STREAMS , 4 }
...

使用性能提示:基本 API

在下面的代码片段中,ov::hint::PerformanceMode::THROUGHPUT 被指定为 compile_model 的 ov::hint::performance_mode 属性:

auto compiled_model = core.compile_model(model, "GPU",
    ov::hint::performance_mode(ov::hint::PerformanceMode::THROUGHPUT));
compiled_model = core.compile_model(model, "GPU", {"PERFORMANCE_HINT": "THROUGHPUT"})

来自应用的其他(可选)提示

我们以一个处理 4 个视频流的应用为例。传达并行闲置限制永不落伍的方法是为性能提示配备可选的 ov::hint::num_requests 配置键,该键设置为 4。如前所述,对于 GPU,这将限制批处理大小,对于 CPU,这将限制推理流的数量,因此每个设备在将提示转换为实际的设备配置选项时都使用 ov::hint::num_requests

// limiting the available parallel slack for the 'throughput' hint via the ov::hint::num_requests
// so that certain parameters (like selected batch size) are automatically accommodated accordingly 
auto compiled_model = core.compile_model(model, "GPU",
    ov::hint::performance_mode(ov::hint::PerformanceMode::THROUGHPUT),
    ov::hint::num_requests(4));
config = {"PERFORMANCE_HINT": "THROUGHPUT",
          "PERFORMANCE_HINT_NUM_REQUESTS": "4"}
# limiting the available parallel slack for the 'throughput'
# so that certain parameters (like selected batch size) are automatically accommodated accordingly
compiled_model = core.compile_model(model, "GPU", config)

最佳推理请求数

使用提示就要求应用查询 ov::optimal_number_of_infer_requests,从而创建并同时运行返回的请求数:

// when the batch size is automatically selected by the implementation
// it is important to query/create and run the sufficient #requests
auto compiled_model = core.compile_model(model, "GPU",
    ov::hint::performance_mode(ov::hint::PerformanceMode::THROUGHPUT));
auto num_requests = compiled_model.get_property(ov::optimal_number_of_infer_requests);
# when the batch size is automatically selected by the implementation
# it is important to query/create and run the sufficient requests
compiled_model = core.compile_model(model, "GPU", {"PERFORMANCE_HINT": "THROUGHPUT"})
num_requests = compiled_model.get_property("OPTIMAL_NUMBER_OF_INFER_REQUESTS")

虽然应用可以根据需要(例如为了支持异步输入填充)自由创建更多请求,但出于效率(设备利用率)原因,至少要并行运行推理请求中的 ov::optimal_number_of_infer_requests ,这一点非常重要。

此外,请注意,ov::hint::PerformanceMode::LATENCY 并不一定意味着使用单个推理请求。例如,多插槽 CPU 可以(以同样的最小延迟)传递与机器上的 NUMA 节点数量一样多的请求。为了使您的应用完全可扩展,最好直接查询 ov::optimal_number_of_infer_requests

倾向异步 API

推理请求的 API 提供同步执行和异步执行。虽然 ov::InferRequest::infer() 本质上是同步的并且操作简单(因为它序列化了当前应用线程中的执行流程),但异步将 infer()“拆分”为 ov::InferRequest::start_async()ov::InferRequest::wait() 的使用(或回调)。请参考 API 示例。虽然同步 API 在开始时比较容易,但在生产代码中,总是倾向于使用异步(基于回调的)API,因为它是为任何可能数量的请求执行流控制的最通用和可扩展的方式(因此也包括延迟和吞吐量情况)。

结合提示和各个低级别设置

虽然在某种程度上牺牲了可移植性,但是可以将提示与各个设备特定的设置结合起来。例如,您可以让设备准备一个配置 ov::hint::PerformanceMode::THROUGHPUT,同时覆盖任何特定值:

{
    // high-level performance hints are compatible with low-level device-specific settings 
auto compiled_model = core.compile_model(model, "CPU",
    ov::hint::performance_mode(ov::hint::PerformanceMode::THROUGHPUT),
    ov::inference_num_threads(4));
}
config = {"PERFORMANCE_HINT": "THROUGHPUT",
          "INFERENCE_NUM_THREADS": "4"}
# limiting the available parallel slack for the 'throughput'
# so that certain parameters (like selected batch size) are automatically accommodated accordingly
compiled_model = core.compile_model(model, "CPU", config)

利用 Benchmark_App 测试提示性能

benchmark_app 具有 C++Python 两种版本,是评估特定设备性能提示的性能的最佳方式:

  • benchmark_app -hint tput -d ‘device’ -m ‘path to your model’

  • benchmark_app -hint latency -d ‘device’ -m ‘path to your model’

禁用提示以模拟提示出现以前的时期(强烈建议在尝试各个低级别设置之前禁用,如下面的流数量、线程等):

    • benchmark_app -hint none -nstreams 1 -d ‘device’ -m ‘path to your model’

另请参阅

支持的设备