CPU デバイス#

CPU プラグインは、インテル® ディストリビューションの OpenVINO™ ツールキットの一部です。インテル® x86-64 および Arm* CPU 上でニューラル・ネットワークのハイパフォーマンス推論を実現するために開発されました。第 11 世代以降のインテル® CPU では、特に INT8 モデルでパフォーマンスが向上しています。CPU プラグインの詳細については、以下を参照してください:

Arm* CPU のプラグイン機能と最適化の範囲は、インテル® x86-64 とは異なる場合があります。明示的に制限が記載されていない場合、機能はすべての CPU アーキテクチャーでサポートされます。 ARM64 上の CPU 推論は Windows* ではサポートされていません。

デバイス名#

CPU デバイス名は CPU プラグインに使用されます。プラットフォーム上に複数の物理ソケットがある場合でも、OpenVINO によってリストされるデバイスは 1 つだけです。マルチソケット・プラットフォームでは、NUMA ノード間の負荷分散とメモリー使用量の分散が自動的に処理されます。推論に CPU を使用するには、デバイス名を ov::Core::compile_model() メソッドに渡す必要があります:

import openvino as ov 

core = ov.Core() 
compiled_model = core.compile_model(model, "CPU")
ov::Core core; 
auto model = core.read_model("model.xml"); 
auto compiled_model = core.compile_model(model, "CPU");

サポートされる推論データタイプ#

CPU プラグインは、内部プリミティブの推論精度として次のデータタイプをサポートします:

  • 浮動小数点データタイプ:

    • f32 (インテル® x86-64、Arm*)

    • bf16 (インテル® x86-64)

    • f16 (インテル® x86-64、Arm*)

  • 整数データタイプ:

    • i32 (インテル® x86-64、Arm*)

  • 量子化データタイプ:

    • u8 (インテル® x86-64)

    • i8 (インテル® x86-64)

    • u1 (インテル® x86-64)

Hello デバイス照会 C++ サンプルを使用すると、検出されたすべてのデバイスでサポートされるデータタイプを出力できます。

量子化データタイプの詳細#

各プリミティブで選択される精度は、IR の演算精度、量子化プリミティブ、および利用可能なハードウェア機能によって異なります。u1/u8/i8 データタイプは量子化された操作でのみ使用されます。つまり、量子化されていない操作には自動的に選択されません。

量子化モデルを取得する方法の詳細については、低精度最適化ガイドを参照してください。

Arm* プラットフォームは、シミュレーション・モードで量子化モデルを実行します。モデル全体 (量子化操作を含む) は浮動小数点精度で実行されます。

浮動小数点タイプの詳細#

CPU プラグインは、内部プリミティブの推論精度として次の浮動小数点データタイプをサポートします:

  • f32 (インテル® x86-64、Arm*)

  • bf16 (インテル® x86-64)

  • f16 (インテル® x86-64、Arm*)

CPU プリミティブのデフォルトの浮動小数点精度は f32 です。float16 をネイティブにサポートしていないプラットフォームで f16 OpenVINO IR をサポートするため、プラグインは内部ですべての f16 値を f32 に変換し、計算は f32 のネイティブ精度で実行されます。半精度計算 (bfloat16 または float16) をネイティブにサポートするプラットフォームでは、パフォーマンスを向上させるために、f32 の代わりに半精度型 (bf16 または f16) が自動的に使用されます (実行モードのヒントを参照)。したがって、bf16 または f16 モデルを実行するのに特別な手順は必要ありません。

重要

bf16 浮動小数点精度には、LLM モデルの推論精度に影響を与えるいくつかの制限があります。詳細はこちらの記事 (英語) を参照してください。

半開区間のを使用すると、以下のようなパフォーマンスの利点が得られます:

  • bfloat16 および float16 データタイプにより、第 4 世代以降のインテル® Xeon® スケーラブル・プロセッサーでインテル® アドバンスト・マトリクス・エクステンション (AMX) が有効になり、多くのディープラーニング操作実装における AVX512 または AVX2 命令と比較して、対応するハードウェアでは計算が大幅に高速化されます。

  • float16 データタイプにより、ARM64 CPU で armv8.2-a+fp16 拡張が有効になり、ベクトル容量が 2 倍になるためパフォーマンスが大幅に向上します。

  • ほとんどの重みテンソルと活性化テンソルは半精度で保存されるため、メモリー・フットプリントが削減されます。

bfloat16 形式の詳細については、 BFLOAT16 – ハードウェア数値定義ホワイトペーパーを参照してください。CPU デバイスが半精度データタイプをサポートできるかどうかを確認するには、 デバイス・プロパティーのインターフェイス照会を使用して ov::device::capabilities プロパティーを照会します。このプロパティーには、CPU 機能のリストに FP16 または BF16 が含まれている必要があります:

core = ov.Core() 
cpu_optimization_capabilities = core.get_property("CPU", device.capabilities)
ov::Core core; 
auto cpuOptimizationCapabilities = core.get_property("CPU", 
    ov::device::capabilities);

推論精度のヒント#

モデルが半精度 (bf16 または f16) に変換されている場合、ov::hint::inference_precisionov::element::bf16 に設定され、ov::CompiledModel::get_property 呼び出しで確認できます。次のコードは、要素タイプを取得する方法を示しています:

core = ov.Core() 
compiled_model = core.compile_model(model, "CPU") 
inference_precision = core.get_property("CPU", hints.inference_precision)
ov::Core core; 
auto network = core.read_model("sample.xml"); 
auto exec_network = core.compile_model(network, "CPU"); 
auto inference_precision = 
    exec_network.get_property(ov::hint::inference_precision);

ネイティブの半精度サポートを持つターゲットで、半精度 (bf16 または f16) ではなく f32 精度でモデルを推論するには、ov::hint::inference_precisionov::element::f32 に設定します。

core = ov.Core() 
core.set_property("CPU", {hints.inference_precision: ov.Type.f32})
ov::Core core; 
core.set_property("CPU", ov::hint::inference_precision(ov::element::f32));

Bfloat16 ソフトウェア・シミュレーション・モードは、ネイティブ avx512_bf16 命令をサポートしないインテル® AVX-512 命令セットを搭載した CPU で使用できます。このモードは開発目的で使用されており、良好なパフォーマンスを保証するものではありません。シミュレーションを有効にするには、ov::hint::inference_precision を明示的に ov::element::bf16 に設定する必要があります。

ネイティブの bfloat16 サポートまたは bfloat16 シミュレーション・モードのない CPU で、ov::hint::inference_precisionov::element::bf16 に設定されると例外がスローされます。

半精度データタイプ (bfloat16 または float16) の仮数サイズが縮小されるため、半精度推論の精度は、特に半精度データタイプを使用してトレーニングされていないモデルの場合、f32 推論と異なる場合があります。半精度の推論精度が許容できない場合は、f32 精度に切り替えることを推奨します。また、パフォーマンスと精度のバランスは、ov::hint::execution_mode ヒントを使用して管理できます。実行モードのヒント を参照してください。

実行モデルのヒント#

ov::hint::inference_precision が明示的に設定されていない場合、ov::hint::execution_mode ヒントを使用することで、実行時の最適化を精度とパフォーマンスのどちらかに向けることができます。ov::hint::execution_modeov::hint::ExecutionMode::PERFORMANCE (デフォルト) に設定され、プラットフォームが半精度計算 (bfloat16 または float16) をネイティブにサポートしている場合、より優れたパフォーマンスを実現するため f32 の代わりに bf16 または f16 タイプが自動的に使用されます。このモードの精度が十分でない場合、ov::hint::execution_modeov::hint::ExecutionMode::ACCURACY に設定して、プラグインが浮動小数点計算で f32 精度を使用するように強制します。

詳細とサンプルコードについては、精度の制御を参照してください。

サポートされる機能#

自動デバイス選択#

システムに CPU 以外の OpenVINO 対応デバイス (統合 GPU など) が含まれている場合、サポートされているモデルはすべてのデバイスで同時に実行できます。これは、ターゲットデバイスとして AUTO:CPU,GPU.0 を指定し、CUMULATIVE_THROUGHPUT パラメーターを追加することによって行われます。

core = ov.Core() 
compiled_model = core.compile_model(model, "AUTO:CPU,GPU.0", {hints.performance_mode: hints.PerformanceMode.CUMULATIVE_THROUGHPUT})
ov::Core core; 
auto model = core.read_model("model.xml"); 
auto compiled_model = core.compile_model(model, "AUTO:CPU,GPU.0", ov::hint::performance_mode(ov::hint::PerformanceMode::CUMULATIVE_THROUGHPUT));

詳細は自動バッチ処理をご覧ください。

マルチストリーム実行#

ov::num_streams(n_streams)n_streams > 1 または ov::hint::performance_mode(ov::hint::PerformanceMode::THROUGHPUT) プロパティーが CPU プラグインで設定されている場合、モデルに対して複数のストリームが作成されます。CPU プラグインの場合、各ストリームには固有のホストスレッドがあるため、受信した推論要求を同時に処理できます。各ストリームは、NUMA ノード間のデータ転送のオーバーヘッドを最小限に抑えるため、NUMA ノードの物理メモリー使用量に対し固有の物理コアグループに固定されます。

詳細については、最適化ガイドスレッド・スケジューリングの概要を参照してください。

レイテンシーに関しては、マルチソケット・プラットフォームで 1 つのストリームのみを実行すると、NUMA ノード間のデータ転送で追加のオーバーヘッドが発生する可能性があることに注意してください。その場合、ov::hint::PerformanceMode::LATENCY パフォーマンス・ヒントを使用することを推奨します。詳細は、パフォーマンスのヒントを参照してください。

動的形状#

CPU は、opset カバレッジの観点から、動的な形状を持つモデルを機能的に完全にサポートします。

CPU プラグインは、ランクが動的に変化するテンソルをサポートしていません。このようなテンソルを使用してモデルを推論すると、例外がスローされます。

一部の実行時の最適化は、モデルの形状が事前に判明している場合、より効果的に機能します。したがって、推論の呼び出し間で入力データの形状が変更されない場合は、静的な形状を持つモデルを使用するか、静的な入力形状で既存のモデルを再形成して最高のパフォーマンスを得ることが推奨されます。

import openvino as ov 

core = ov.Core() 
model.reshape([10, 20, 30, 40])
ov::Core core; 
auto model = core.read_model("model.xml"); 
ov::Shape static_shape = {10, 20, 30, 40}; 

model->reshape(static_shape);

詳細については、動的形状ガイドを参照してください。

前処理の高速化#

CPU プラグインは、前処理操作の完全なセットをサポートし、それらの前処理操作に高パフォーマンスの実装を提供します。詳細については、前処理 API ガイドを参照してください。

テンソルの精度変換を処理する CPU プラグインのサポートは、次の ov::element タイプに限定されます:
  • bf16

  • f16

  • f32

  • f64

  • i8

  • i16

  • i32

  • i64

  • u8

  • u16

  • u32

  • u64

  • boolean

モデルのキャッシュ#

CPU はネットワークのインポート/エクスポート機能をサポートします。共通の OpenVINO™ ov::cache_dir プロパティーによってモデルのキャッシュが有効になっている場合、プラグインはモデルのコンパイル中に指定されたディレクトリー内にキャッシュされた BLOB を自動的に作成します。キャッシュされた BLOB には、一般的な実行時の最適化と低精度の変換が行われた、ネットワークの部分的な表現が含まれています。次のモデルがコンパイルされるとき、最初の OpenVINO IR ではなく、キャッシュされた表現がプラグインにロードされるため、変換手順はスキップされます。これらの変換はモデルのコンパイルにかなりの時間がかかるため、この表現をキャッシュすることで、その後のモデルのコンパイルにかかる時間が短縮され、その結果、最初の推論レイテンシー (FIL) が短縮されます。

詳細は、モデルのキャッシュを参照してください。

拡張性#

CPU プラグインは、プラグインにそのような操作用の実装がない場合、ov::Op リファレンス実装でのフォールバックをサポートします。つまり、OpenVINO™ 拡張メカニズムはプラグイン拡張にも使用できるということです。カスタム操作の実装でフォールバックを有効にするには、派生操作クラスの ov::Op::evaluate メソッドをオーバーライドします (詳細については、カスタム OpenVINO™操作を参照してください)。

ステートフル・モデル#

CPU プラグインは、ステートフル・モデルを制限なくサポートします。

詳細については、ステートフル・モデルのガイドをご覧ください。

サポートされるプロパティー#

プラグインは以下のプロパティーをサポートしています:

read-write プロパティー#

すべてのパラメーターは、ov::Core::compile_model() を呼び出す前に設定するか、追加の引数として ov::Core::compile_model() に渡す必要があります。

  • ov::enable_profiling

  • ov::hint::inference_precision

  • ov::hint::performance_mode

  • ov::hint::execution_mode

  • ov::hint::num_request

  • ov::hint::scheduling_core_type

  • ov::hint::enable_hyper_threading

  • ov::hint::enable_cpu_pinning

  • ov::num_streams

  • ov::affinity

  • ov::inference_num_threads

  • ov::cache_dir

  • ov::intel_cpu::denormals_optimization

  • ov::intel_cpu::sparse_weights_decompression_rate

read 専用プロパティー#

  • ov::supported_properties

  • ov::available_devices

  • ov::range_for_async_infer_requests

  • ov::range_for_streams

  • ov::device::full_name

  • ov::device::capabilities

ov::affinityov::hint::enable_cpu_pinning に置き換えられました。そのため、2024.0 リリースから非推奨となり、2025 リリースでは削除されます。

外部への依存関係#

一部のパフォーマンスが重要な DL 操作では、CPU プラグインはサードパーティーのライブラリーを使用します:

最適化ガイド#

マルチスレッドの最適化#

CPU 推論は、複数の論理プロセッサーで 1 つまたは複数の入力を並行して推論します。

詳細はスレッド・スケジュールの概要をご覧ください。

デノーマル最適化#

非正規数 (デノーマル) は、ゼロではなく、ゼロに非常に近い有限浮動小数点数です。例: (0、1.17549e-38) と (0、-1.17549e-38) の数値。このような場合、正規化数値エンコード形式には数値をエンコードする機能がないため、アンダーフローが発生します。このような数値を含む計算は、多くのハードウェアでは非常に低速になります。

非正規数はゼロに非常に近いため、非正規数を直接ゼロとして扱うことは、非正規数の計算を最適化する簡単な方法です。しかし、この最適化は IEEE 754 標準に準拠していません。これが許容できない精度の低下を引き起こす場合、この振舞いを制御するために denormals_optimization プロパティーが導入されました。ユースケースに非正規数があり、精度の低下が見られないか許容範囲内の場合は、プロパティーを True に設定してパフォーマンスを向上させます。それ以外は False に設定します。プロパティーによって明示的に設定されておらず、アプリケーションが非正規化の最適化も行わない場合、最適化はデフォルトで無効になります。denormals_optimization プロパティーを有効にすると、OpenVINO はクロスオペレーション・システム/コンパイラーを提供し、該当する場合はすべてのプラットフォームで安全な最適化を提供します。

OpenVINO が使用されるアプリケーションでも、この低レベルの非正規化最適化が実行される場合があります。OpenVINO が呼び出されるスレッドの先頭で MXCSR レジスターに FTZ (Flush-To-Zero) フラグと DAZ(Denormals-As-Zero) フラグを設定することで最適化された場合、OpenVINO は同じスレッドおよびサブスレッドでこの設定を継承するため、denormals_optimization プロパティーを設定する必要はありません。このような場合、設定の有効性と安全性についてはユーザーの責任となります。

denormals_optimization プロパティーは、compile_model() を呼び出す前に設定する必要があります。

アプリケーションで非正規化の最適化を有効にするには、denormals_optimization プロパティーを True に設定する必要があります:

import openvino.properties.intel_cpu as intel_cpu 

core = ov.Core() 
core.set_property("CPU", intel_cpu.denormals_optimization(True)) 
compiled_model = core.compile_model(model=model, device_name=device_name)
ov::Core core; // ステップ 1: ov::Core オブジェクトの作成 
core.set_property(ov::intel_cpu::denormals_optimization(true)); // ステップ 1b: デノーマル最適化を有効にする 
auto model = core.read_model(modelPath); // ステップ 2: モデルの読み込み 
//... 
// ステップ 3: 入力/出力を準備 
//...
// ステップ 4: デバイス構成を設定 
auto compiled = core.compile_model(model, device, config); // ステップ 5: LoadNetwork

スパース重みの復元 (インテル® x86-64)#

スパース重みは、ほとんどの要素がゼロである重みです。すべての要素の数に対するゼロ要素の数の比率は、スパース率と呼ばれます。したがって、スパース重みはスパース率が高い重みであると仮定します。スパース重みでは、特殊なストレージ構造を使用してゼロ値以外のみをメモリーに保存できるため、メモリーをより効率的に使用できます。これにより、メモリー要求の高いワークロード (スループット・シナリオなど) でのパフォーマンスが向上します。

スパース重みの復元機能を使用すると、モデルのコンパイル段階で行列乗算演算の重みを CPU プラグインに直接パックし、ゼロ以外の値を特別なパック形式で保存できます。その後、モデルの実行中に重みが復元され、計算カーネルで使用されます。重みはパック形式で DDR/L3 キャッシュからロードされるため、メモリー消費量が大幅に削減され、その結果推論パフォーマンスが向上します。

この機能を使用するには、インターバル [0, 1] から値を取得できる sparse_weights_decompression_rate プロパティーがユーザーに提供されます。sparse_weights_decompression_rate は、スパース率のしきい値を定義します。スパース率が高い操作のみが、スパース重み復元機能を使用して実行されます。デフォルト値は 1 で、オプションが無効であることを意味します。

スパース重み復元機能はデフォルトで無効になっています。これは、全体の速度向上は特定のワークロードに大きく依存し、場合によってはこの機能によりパフォーマンスの低下が生じる可能性があるためです。

sparse_weights_decompression_rate の使用方法のコード例:

import openvino.properties.intel_cpu as intel_cpu 

core = ov.Core() 
core.set_property("CPU", intel_cpu.sparse_weights_decompression_rate(0.8)) 
compiled_model = core.compile_model(model=model, device_name=device_name)
ov::Core core; // ステップ 1: ov::Core オブジェクトの作成 
core.set_property(ov::intel_cpu::sparse_weights_decompression_rate(0.8)); // ステップ 1b: スパース重み復元機能を有効にする 
auto model = core.read_model(modelPath); // ステップ 2: モデルの読み込み 
//... 
// ステップ 3: 入力/出力を準備 
//...
// ステップ 4: デバイス構成を設定 
auto compiled = core.compile_model(model, device, config); // ステップ 5: LoadNetwork

sparse_weights_decompression_rate プロパティーは、compile_model() を呼び出す前に設定する必要があります。

スパース重み復元機能が適用されたレイヤーの情報は、パフォーマンス・カウンター・ログから取得できます。“exec type” フィールドには、“sparse” パーティクルを含む実装タイプが含まれます (以下の例では “brgemm_avx512_amx_sparse_I8”)。

MatMul_1800 EXECUTED layerType: FullyConnected execType: brgemm_avx512_amx_sparse_I8 realTime (ms): 0.050000 cpuTime (ms): 0.050000

制限事項#

現在、スパース重み復元機能は、次の制限付きでサポートされています:

  1. モデルは int8 精度に量子化する必要があります。

  2. この機能は、行列乗算演算でのみサポートされます。

  3. ハードウェア・ターゲットはインテル® AMX 拡張機能をサポートしている必要があります (例: 第 4 世代インテル® Xeon® プロセッサー (開発コード名 Sapphire Rapids))。

  4. 重みの入力および出力チャネルの数は 64 の倍数である必要があります。

関連情報#