CPU デバイス

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

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

デバイス名

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)

  • 整数データタイプ:

    • 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)

CPU プリミティブのデフォルトの浮動小数点精度は f32 です。f16 OpenVINO IR をサポートするため、プラグインは内部ですべての f16 値を f32 に変換し、計算は f32 のネイティブ精度で実行されます。bfloat16 計算をネイティブにサポートするプラットフォーム AVX512_BF16 または AMX 拡張子を持つ) では、パフォーマンスを向上させるため f32 の代わりに bf16 タイプが自動的に使用されます (実行モードのヒントを参照)。したがって、bf16 モデルを実行するのに特別な手順は必要ありません。bfloat16 形式の詳細については、BFLOAT16 – ハードウェア数値定義ホワイトペーパーを参照してください。

bf16 精度を使用すると、次のようなパフォーマンス上の利点が得られます。

  • bfloat16 データタイプにより、インテル® アドバンスト・マトリクス・エクステンション (インテル® AMX) が利用できます。これにより、多くの DL 操作実装における AVX512 または AVX2 命令と比較して、対応するハードウェア上では劇的に計算が高速化されます。

  • bfloat16 データのサイズは 32 ビット float の半分であるため、メモリー消費量が削減されます。

CPU デバイスが bfloat16 データタイプをサポートできるかどうかを確認するには、デバイス・プロパティーのインターフェイス照会を使用して ov::device::capabilities プロパティーを照会します。このプロパティーには、CPU 機能のリストに 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 に変換されている場合、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 サポートを持つターゲットで bf16 ではなく 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 データタイプは仮数サイズが小さいため、特に bfloat16 データタイプでトレーニングされていないモデルの場合、結果として得られる bf16 推論の精度は f32 推論とは異なる場合があります。bf16 の推論精度が許容できない場合は、f32 精度に切り替えることを推奨します。また、パフォーマンスと精度のバランスは、ov::hint::execution_mode ヒントを使用して管理できます。実行モードのヒントを参照してください。

実行モデルのヒント

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

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

サポートされる機能

マルチデバイス実行

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

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

詳細については、マルチデバイス実行を参照してください。

マルチストリーム実行

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 パフォーマンス・ヒントを使用することを推奨します。詳細は、パフォーマンスのヒントを参照してください。

マルチストリームの実行は、Arm® プラットフォームではサポートされていません。レイテンシーとスループットのヒントは同じ動作を指示し、推論に 1 つのストリームのみを使用します。

動的形状

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

外部への依存関係

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

最適化ガイド

マルチスレッドの最適化

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

ユーザーは次のプロパティーを使用して、モデルの推論に使用できる CPU リソースを制限できます。プラットフォームまたはオペレーティング・システムがこの動作をサポートできる場合、OpenVINO ランタイムは、限られた利用可能な CPU に基づいてマルチスレッドのスケジュールを行います。

  • ov::inference_num_threads は、CPU 推論に使用される論理プロセッサーの数を制限します。設定した数がプラットフォーム上の論理プロセッサー数より大きい場合、マルチスレッド・スケジューラーは CPU の推論にプラットフォーム番号のみを使用します。

  • ov::hint::scheduling_core_type は、ユーザーが Performance-cores (P-cores) と Efficient-cores (E-cores) の両方を含むハイブリッド・プラットフォームで推論を実行する場合、CPU 推論の CPU コアのタイプを制限します。ユーザー・プラットフォームに 1 種類の CPU コアしかない場合、このプロパティーは効果がなく、CPU 推論では常にこの一意のコアタイプが使用されます。

  • ov::hint::enable_hyper_threading は、プラットフォームで CPU のハイパースレッディングが有効になっている場合、CPU コアごとに 1 つまたは 2 つの論理プロセッサーの使用を制限します。E-cores など、CPU コアごとの論理プロセッサーが 1 つだけの場合、このプロパティーは効果がなく、CPU 推論ではすべての論理プロセッサーが使用されます。

# Use one logical processor for inference
compiled_model_1 = core.compile_model(
    model=model,
    device_name=device_name,
    config={properties.inference_num_threads(): 1},
)

# Use logical processors of Efficient-cores for inference on hybrid platform
compiled_model_2 = core.compile_model(
    model=model,
    device_name=device_name,
    config={
    properties.hint.scheduling_core_type(): properties.hint.SchedulingCoreType.ECORE_ONLY,
                                                },
)

# Use one logical processor per CPU core for inference when hyper threading is on
compiled_model_3 = core.compile_model(
    model=model,
    device_name=device_name,
    config={properties.hint.enable_hyper_threading(): False},
)
        // Use one logical processor for inference
        auto compiled_model_1 = core.compile_model(model, device, ov::inference_num_threads(1));

        // Use logical processors of Efficient-cores for inference on hybrid platform
        auto compiled_model_2 = core.compile_model(model, device, ov::hint::scheduling_core_type(ECORE_ONLY));

        // Use one logical processor per CPU core for inference when hyper threading is on
        auto compiled_model_3 = core.compile_model(model, device, ov::hint::enable_hyper_threading(false));

ov::hint::scheduling_core_type および ov::hint::enable_hyper_threading は、現在のリリースでは Linux* および Windows* が動作するインテル® x86-64 CPU のみをサポートします。

デフォルトでは、OpenVINO ランタイムはパフォーマンスを向上させるため CPU スレッドの固定 (ピニング) を有効にします。ユーザーは、ov::hint::enable_cpu_pinning プロパティーを使用してピニングをオフにすることもできます。スレッドのピニングを無効にすると、複数のワークロードが並行して実行される複雑なアプリケーションでは有益である可能性があります。

# Disable CPU threads pinning for inference when system supoprt it
compiled_model_4 = core.compile_model(
    model=model,
    device_name=device_name,
    config={properties.hint.enable_cpu_pinning(): False},
)
        // Disable CPU threads pinning for inference when system support it
        auto compiled_model_4 = core.compile_model(model, device, ov::hint::enable_cpu_pinning(false));

マルチストリーム実行の詳細については、最適化ガイドを参照してください。

ov::hint::enable_cpu_pinning 現在のリリースでは Linux* のみがサポートされます。

デノーマルの最適化

非正規数 (デノーマル) は、ゼロではなく、ゼロに非常に近い有限浮動小数点数です。
例: (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;                                                    // Step 1: create ov::Core object
        core.set_property(ov::intel_cpu::denormals_optimization(true));   // Step 1b: Enable denormals optimization
        auto model = core.read_model(modelPath);                          // Step 2: Read Model
        //...                                                             // Step 3: Prepare inputs/outputs
        //...                                                             // Step 4: Set device configuration
        auto compiled = core.compile_model(model, device, config);        // Step 5: LoadNetwork

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

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

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

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

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

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;                                                              // Step 1: create ov::Core object
        core.set_property(ov::intel_cpu::sparse_weights_decompression_rate(0.8));   // Step 1b: Enable sparse weights decompression feature
        auto model = core.read_model(modelPath);                                    // Step 2: Read Model
        //...                                                                       // Step 3: Prepare inputs/outputs
        //...                                                                       // Step 4: Set device configuration
        auto compiled = core.compile_model(model, device, config);                  // Step 5: LoadNetwork

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

sparse weights decompression feature が適用されたレイヤーの情報は、パフォーマンス・カウンター・ログから取得できます。“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 の倍数である必要があります。