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_precision
は ov::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_precision
を ov::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_precision
が ov::element::bf16
に設定されると例外がスローされます。
注
bfloat16
データタイプは仮数サイズが小さいため、特に bfloat16
データタイプでトレーニングされていないモデルの場合、結果として得られる bf16
推論の精度は f32
推論とは異なる場合があります。bf16
の推論精度が許容できない場合は、f32
精度に切り替えることを推奨します。また、パフォーマンスと精度のバランスは、ov::hint::execution_mode
ヒントを使用して管理できます。実行モードのヒントを参照してください。
実行モデルのヒント¶
ov::hint::inference_precision
が明示的に設定されていない場合、ov::hint::execution_mode
ヒントを使用することで、実行時の最適化を精度とパフォーマンスのどちらかに向けることができます。ov::hint::execution_mode
が ov::hint::ExecutionMode::PERFORMANCE
(デフォルト) に設定されており、プラットフォームが bfloat16
計算をネイティブにサポートしている (AVX512_BF16
または AMX
拡張がある) 場合、f32
の代わりに bf16
タイプが自動的に使用され、より良いパフォーマンスを得られます。このモードの精度が十分でない場合、ov::hint::execution_mode
を ov::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™操作を参照してください)。
サポートされるプロパティー¶
プラグインは以下のプロパティーをサポートしています。
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
制限事項¶
現在、スパース重み復元機能は、次の制限付きでサポートされています。
モデルは int8 精度に量子化する必要があります。
この機能は、行列乗算演算でのみサポートされます。
ハードウェア・ターゲットはインテル® AMX 拡張機能をサポートしている必要があります (例: 第 4 世代インテル® Xeon® プロセッサー (開発コード名 Sapphire Rapids))。
重みの入力および出力チャネルの数は 64 の倍数である必要があります。