インテル® Software Development Emulator (インテル® SDE) は、ソフトウェア開発者向けにインテル社から公開されているインテル® プロセッサーのソフトウェア・エミュレーターです。2019 年 5 月時点の最新バージョンは 8.35 で、開発コード名 Ice Lake-Client と開発コード名 Ice Lake-Server までのプロセッサーがサポートされています。
前の記事で紹介したように、インテル® C/C++ および Fortran コンパイラー 19 Update 4 は、開発コード名 Ice Lake-Client と開発コード名 Ice Lake-Server でサポートされるインテル® アドバンスト・ベクトル・エクステンション 512 (インテル® AVX-512) 命令セットを生成することができます。発表前のプロセッサーは、一部のメーカーや恵まれた人々しか利用できないため、私たちはエミュレーションが唯一の検証手段です。
エミュレーション環境でプログラム全体を実行すると、もちろん実行時間は数十倍から数百倍遅くなります。しかし、独自にプロセッサーを判定して実行するコードを切り分けるコードの動作を確認したり、アルゴリズムの設計段階で特定の機能のみに新しい命令セットを使用して単体検証するようなケースでは十分に利用できるかもしれません。
この記事ではインテル® SDE の Windows* 版を使用していくつかの利用例を紹介します。インテル® SDE は、https://software.intel.com/en-us/isa-extensions から無料で入手できます。ダウンロードしたパッケージを展開すると、インストールすることなく実行できます。システムにウイルス対策ツールが導入されている場合、インテル® SDE を実行すると保護対象として保護される可能性があります。展開先のディレクトリーを保護から除外することでこの問題は解決できるでしょう。
Windows* 環境では、ダウンロードしたバージョン 8.35 のパッケージを展開すると、sde-external-8.35.0-2019-03-11-win
というディレクトリーが作成されました。ディレクトリーの内容を確認すると次のような構造です。このディレクトリーを環境変数 PATH に手動で追加します (例: set PATH=%PATH%; C:\sde-external-8.35.0-2019-03-11-win
)。
通常起動に使用するファイルは、sde.exe
と sde-win.bat
です。
sde を直接起動
sde
はインテル® SDE の本体です。このコマンドを使用する場合、次の形式でコマンドを入力します。sde
のコマンドオプションとアプリケーションは、– で分離する必要があります。
$ sde <sde のオプション> -- <実行するアプリケーション> <.アプリケーションの引数>
例えば、icl pi.c /QxICELAKE-CLIENT
で開発コード名 Ice Lake-Client でサポートされるインテル® AVX-512 命令セットを使用したバイナリーを生成すると、現在利用可能なプロセッサーでは実行できませんが、
$ sde –icl –- pi ここで、-icl は開発コード名 Ice Lake-Client をエミュレーション・ターゲットにするオプション
を実行すると、バイナリーをエミュレーションして実行できます。以下は、実際にインテル® Core™ i7-9700K プロセッサー上で実行した例です。
実行時間は、インテル® AVX2 を使用してインテル® Core™ i7-9700K プロセッサーで実行したバイナリーよりも、インテル® AVX-512 をエミュレーションしたバイナリーのほうが 20 倍程度遅くなっています。エミュレーション速度の低下は、実際にエミュレーションされる命令数よって異なります。
インテル® SDE は単にバイナリーをエミュレーションするだけではなく、エミュレーションしたバイナリーの統計情報を生成できます。
$ sde –icl –mix –- pi -mix オプションを追加
-mix
オプションを追加して実行すると統計情報ファイル sde-mix-out.txt
が現在のディレクトリーに生成されます。
ファイルの一部を見てみます。
# ============================================== # STATS FOR TID 0 OS-TID 1344 EMIT# 1 # ============================================== # EMIT_TOP_BLOCK_STATS FOR TID 0 OS-TID 1344 EMIT # 1 EVENT=ICOUNT BLOCK: 0 PC: 00007ff7e9fe10df ICOUNT: 968750000 EXECUTIONS: 31250000 #BYTES: 178 %: 99.6 cumltv%: 99.6 FN: .text IMG: C:\Users\kiyo\Desktop\2019\FTF_expert\code\pi\pi.exe OFFSET: 10df XDIS 00007ff7e9fe10df: BASE 83C020 add eax, 0x20 XDIS 00007ff7e9fe10e2: AVX512EVEX 62C17E48E6C6 vcvtdq2pd zmm16, ymm14 XDIS 00007ff7e9fe10e8: AVX512EVEX 62A1E54858C8 vaddpd zmm17, zmm3, zmm16 XDIS 00007ff7e9fe10ee: AVX512EVEX 62A1DD4859D1 vmulpd zmm18, zmm4, zmm17 XDIS 00007ff7e9fe10f4: AVX512EVEX 62E2ED40A8D0 vfmadd213pd zmm18, zmm18, zmm0 XDIS 00007ff7e9fe10fa: AVX512EVEX 62A1F5485EDA vdivpd zmm19, zmm1, zmm18 XDIS 00007ff7e9fe1100: AVX512EVEX 6221854858DB vaddpd zmm27, zmm15, zmm19 XDIS 00007ff7e9fe1106: AVX2 C50DFEFA vpaddd ymm15, ymm14, ymm2 XDIS 00007ff7e9fe110a: AVX512EVEX 62C17E48E6E7 vcvtdq2pd zmm20, ymm15 XDIS 00007ff7e9fe1110: AVX512EVEX 62A1E54858EC vaddpd zmm21, zmm3, zmm20 XDIS 00007ff7e9fe1116: AVX512EVEX 62A1DD4859F5 vmulpd zmm22, zmm4, zmm21 XDIS 00007ff7e9fe111c: AVX512EVEX 62E2CD40A8F0 vfmadd213pd zmm22, zmm22, zmm0 XDIS 00007ff7e9fe1122: AVX512EVEX 62A1F5485EFE vdivpd zmm23, zmm1, zmm22 XDIS 00007ff7e9fe1128: AVX512EVEX 6231D54858F7 vaddpd zmm14, zmm5, zmm23 XDIS 00007ff7e9fe112e: AVX2 C585FEEA vpaddd ymm5, ymm15, ymm2 XDIS 00007ff7e9fe1132: AVX512EVEX 62615528FEEA vpaddd ymm29, ymm5, ymm2 XDIS 00007ff7e9fe1138: AVX512EVEX 62617E48E6C5 vcvtdq2pd zmm24, ymm5 XDIS 00007ff7e9fe113e: AVX512EVEX 6201E54858C8 vaddpd zmm25, zmm3, zmm24 XDIS 00007ff7e9fe1144: AVX512EVEX 6201DD4859D1 vmulpd zmm26, zmm4, zmm25 XDIS 00007ff7e9fe114a: AVX512EVEX 6262AD40A8D0 vfmadd213pd zmm26, zmm26, zmm0 XDIS 00007ff7e9fe1150: AVX512EVEX 6201F5485EE2 vdivpd zmm28, zmm1, zmm26 XDIS 00007ff7e9fe1156: AVX512EVEX 6211A54058FC vaddpd zmm15, zmm27, zmm28 XDIS 00007ff7e9fe115c: AVX512EVEX 62017E48E6F5 vcvtdq2pd zmm30, ymm29 XDIS 00007ff7e9fe1162: AVX512EVEX 6201E54858FE vaddpd zmm31, zmm3, zmm30 XDIS 00007ff7e9fe1168: AVX512EVEX 6291DD4859EF vmulpd zmm5, zmm4, zmm31 XDIS 00007ff7e9fe116e: AVX512EVEX 62F2D548A8E8 vfmadd213pd zmm5, zmm5, zmm0 XDIS 00007ff7e9fe1174: AVX512EVEX 6261F5485EF5 vdivpd zmm30, zmm1, zmm5 XDIS 00007ff7e9fe117a: AVX512EVEX 62918D4858EE vaddpd zmm5, zmm14, zmm30 XDIS 00007ff7e9fe1180: AVX512EVEX 62711520FEF2 vpaddd ymm14, ymm29, ymm2 XDIS 00007ff7e9fe1186: BASE 3D00CA9A3B cmp eax, 0x3b9aca00 XDIS 00007ff7e9fe118b: BASE 0F824EFFFFFF jb 0x7ff7e9fe10df …
実行された命令のアセンブリー・リストが表示されていますが、このリストで、「XDIS 00007ff7e9fe10e2: VX512EVEX」のように AVX512EVEX と示されている命令がインテル® AVX-512 命令でエミュレーションされた命令です。このアセンブリーは、数値積分を使用して PI を計算する以下のループ、
for (i=0;i< num_steps; i++){ x = (i+0.5)*step; sum = sum + 4.0/(1.0+x*x); }
です。ここで使用するデータ型は double
であるため、インテル® AVX-512 では 8 個の要素を SIMD 計算できます。また、4 つの vfmadd213pd
命令が生成され、ループは 4 回アンロールされていることから、ループ・インデックスは、4 x 8 = 32 (0x20) でインクリメントされていることが分かります (先頭の add eax, 0x20
命令)。
これ以外に命令のカテゴリー別の実行回数を見ることもできます。
# END_TOP_BLOCK_STATS # EMIT_DYNAMIC_STATS FOR TID 0 OS-TID 1344 EMIT #1 # # $dynamic-counts # # TID 0 # opcode count # *mem-atomic 1753 *stack-read 61484 *stack-write 115261 *iprel-read 13114 *iprel-write 1237 *mem-read-1 322865 *mem-read-2 302421 *mem-read-4 47228 *mem-read-8 92692 *mem-read-16 6379 *mem-read-32 2 *mem-read-64 88 *mem-write-1 106294 *mem-write-2 15132 *mem-write-4 43894 *mem-write-8 82703 *mem-write-16 13235 *mem-write-64 1 *mem-write-512 1 *mem-read 771675 *mem-write 261260 *mem 1024189 *isa-ext-3DNOW 83 *isa-ext-AVX 84 *isa-ext-AVX2 62500000 *isa-ext-AVX512EVEX 812500016 *isa-ext-BASE 97353540 *isa-ext-FMA 14 …
これらの情報は新しい命令セットがどれくらい実行されているか判断するのに役立ちます。
sde.exe
では実行時に次のようにプロセッサーを明示的に指定することができます。
次のようなプロセッサーを手動で判定する処理を考えてみます。
#define KNL ( _FEATURE_AVX512F | _FEATURE_AVX512ER | _FEATURE_AVX512PF | _FEATURE_AVX512CD ) #define CAS ( _FEATURE_AVX512DQ | _FEATURE_AVX512F | _FEATURE_AVX512CD | _FEATURE_AVX512BW | _FEATURE_AVX512VL ) #define ICL ( _FEATURE_AVX512DQ | _FEATURE_AVX512F | _FEATURE_AVX512CD | _FEATURE_AVX512BW | _FEATURE_AVX512VL | _FEATURE_AVX512IFMA52 | _FEATURE_AVX512VBMI | _FEATURE_AVX512_VPOPCNTDQ | _FEATURE_AVX512_BITALG | _FEATURE_AVX512_VBMI2 | _FEATURE_GFNI | _FEATURE_VAES | _FEATURE_VPCLMULQDQ | _FEATURE_AVX512_VNNI | _FEATURE_RDPID ) int main(int argc, char *argv[]) { if ( _may_i_use_cpu_feature( (unsigned long) ICL ) ) printf("この CPU は、AVX-512F+DQ+CD+BW+VL 命令セットをサポートする IceLake Client プロセッサーです。\n"); else if ( _may_i_use_cpu_feature( (unsigned long) CAS ) ) printf("この CPU は、AVX-512F+DQ+CD+BW+VL 命令セットをサポートする CascadeLake プロセッサーです。\n"); else if ( _may_i_use_cpu_feature( (unsigned long) KNL ) ) printf("この CPU は、AVX-512F+CD+ER+PF 命令セットをサポートする Knights Landing プロセッサーです。\n"); else printf("この CPU は AVX-512 命令セットをサポートしていません。\n"); }
このコードを icl cupid.c
でコンパイルして、インテル® Core™ i7-9700K プロセッサーで実行してみます。
当然、define
文で指定される CPUID の機能ビットはサポートされないため、上記のメッセージが出力されます。では、インテル® SDE によるエミュレーションで、開発コード名 Ice Lake-Client (-icl)、開発コード名 Cascade Lake (-clx)、そして開発コード名 Kights Landing (-knl) のチェック機能をそれぞれ確認してみます。
インテル® SDE はエミュレートする機能を特定するため CPUID を照合します。また、エミュレートされた機能をチェックするコンパイル済みアプリケーションに対し、それらが存在することを通知するため CPUID の出力を変更します。これにより、チェックが正しく行われていることが確認できました。
sde-win.bat を使用する
このバッチファイルの中身は、sde –- cmd.exe
です。Linux* や macOS* 環境でも sde –- ksh
のようにシェルをインテル® SDE 環境下で起動することができます。このバッチファイルを起動すると、Windows* ではコマンドプロンプトが開き、この中で実行されるコマンドはすべてインテル® SDE のエミュレーション環境で実行されます。エミュレーション対象のプロセッサーを変更する場合、前述のオプションをバッチファイルに加えると良いでしょう (sde –clx –- cmd.exe
のように)。
cupid
のプロセッサー・チェックをこの環境で実行すると次のようになります。
このウィンドウで起動されるすべてのバイナリーは、インテル® SDE の制御下で実行されるため、エミュレーションが行われなくても実行速度は遅くなります。次の例は、インテル® AVX2 命令セットの最適化オプションを指定して生成したプログラムですが、描画性能は 86FPS であると示されています (プログラム・ウィンドウの上部)。
通常のコマンドプロンプトで実行すると、1452FPS ですのでほぼ 1/120 のパフォーマンスであることが分かります。
sde-win.bat
やシェルのエミュレーション環境を使用すると、簡単に異なるプロセッサー環境を用意することができます。
インテル® SDE の使い方や、Windows*、Linux* および macOS* での詳しい導入方法については、こちらの記事をご覧ください。このエミュレーターは、プロセッサーのリリースが計画されると随時更新されているようなので、今後登場するさたに未知のプロセッサーのエミュレーションも利用できるようになるでしょう。
発表済みの開発コード名 Cascade Lake をまだ入手できない、または開発コード名 Ice Lake にいち早く対応したい、と思われている開発者の方は是非このツールを活用してみてください。