Intel Code Modernization 2017に参加した
Intel Code Modernization 2017に参加した。Intel流のParallel Computingについての情報やそれに対する知見を得た。その際に個人的に印象深かったAVX512命令であるが、当然ながら今現在でその命令に完全対応したコンシュマー向けのアーキテクチャは存在しない*1。 しかし、エミューレータがあるというお話だったので、手元のマシンでも命令を動かして見る事にした。*2
現代のマシンでAVX512命令をエミュレートする遊び
エミュレータはWindowsとLinuxに対応しているようだが、Microsoft側の閉鎖的な開発コミュニティによってIntel側のライブラリの開発が順調でないという旨をセミナーで聞いたので、やはりLinux上で動かすのが好ましいだろう。カーネルの改変なども当然ながらLinux上でなければ不可能であるし。
環境
% uname -a Linux roki-VB 4.8.0-27-generic #29-Ubuntu SMP Thu Oct 20 21:03:13 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux % cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 69 model name : Intel(R) Core(TM) i5-4308U CPU @ 2.80GHz stepping : 1 cpu MHz : 2800.000 cache size : 3072 KB physical id : 0 siblings : 1 core id : 0 cpu cores : 1 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc eagerfpu pni pclmulqdq monitor ssse3 cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx rdrand hypervisor lahf_lm abm bugs : bogomips : 5600.00 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual
準備
まずLicense Agreement to Download | Intel® Softwareからエミュレータを、GCC for Intel AVX-512, Intel MPX and Intel SHA extensionsからGCC、GDBをダウンロードする。
% mkdir $HOME/mpx % export MPX_HOME="$HOME/mpx" % cd $MPX_HOME % tar xvf ../sde-external-7.49.0-2016-07-07-lin.tar.bz2 % tar xvf ../2014-02-13-mpx-runtime-external-lin.tar.bz2 % tar xvf ../binutils-gdb_install_2.24.51.20140422.tar.gz % tar xvf ../gcc_5.0.0-mpx-r214719-src.tar.gz % mv sde-external-7.49.0-2016-07-07-lin.tar.bz2 $MPX_HOME % mv 2014-02-13-mpx-runtime-external-lin.tar.bz2 $MPX_HOME % mv binutils-gdb_install_2.24.51.20140422.tar.gz $MPX_HOME
GCCのビルド。とりあえずconfigureを走らせると、必要なライブラリなどがあれば止まるのでそれ頼りで。インストールは$HOME/local、3 stage buildはdisable。
% cd gcc_install_5.0.0-mpx-r214719 % mkdir objdir && cd objdir % ./configure --prefix=$HOME/local --disable-bootstrap ... configure: error: Building GCC requires GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+. Try the --with-gmp, --with-mpfr and/or --with-mpc options to specify
ということでエラー通りにライブラリを導入する。
% mkdir gmp mpfr mpc % cd gmp && wget ftp://ftp.gmplib.org/pub/gmp/gmp-5.1.3.tar.bz2 && tar xf gmp-5.1.3.tar.bz2 && rm *.tar.bz2 && mv gmp-5.1.3/* ./ % cd ../mpfr && wget http://www.mpfr.org/mpfr-current/mpfr-3.1.5.tar.gz && tar xf mpfr-3.1.5.tar.gz && rm *.tar.gz && mv mpfr-3.1.5/* ./ % cd ../mpc && wget http://www.multiprecision.org/mpc/download/mpc-1.0.3.tar.gz && tar xf mpc-1.0.3.tar.gz && rm *.tar.gz && mv mpc-1.0.3/* ./
さて、再度configureを実行してビルド、インストールする。
% ./configure --prefix=$HOME/local --disable-bootstrap % make % sudo make install
そしてパスを通す。
% export SDE_KIT=$MPX_HOME/sde-external-7.49.0-2016-07-07-lin % export MPX_RUNTIME_LIB=$MPX_HOME/2014-02-13-mpx-runtime-external-lin % export MPX_BINUTILS=$MPX_HOME/binutils-gdb_install_2.24.51.20140422 % export MPX_GCC=$HOME/local
動かす
コードは以下のような感じ。まあ内容は、512ビットのデータを32ビットの整数に16分割したデータを2つ用意し、そいつらをAVX512を利用して各々のデータを加算するといったもの。
#include<iostream> #include<iterator> #include<cstdint> #include<boost/range/algorithm_ext/iota.hpp> #include<boost/range/algorithm/for_each.hpp> #include<boost/range/algorithm/copy.hpp> namespace{ constexpr std::size_t S=16; } std::uint32_t a[S] __attribute__((aligned(64)))={}; std::uint32_t b[S] __attribute__((aligned(64)))={}; std::uint32_t result[S] __attribute__((aligned(64)))={}; inline void init() { boost::range::iota(a,0); boost::range::iota(b,0); boost::range::for_each(b,[](std::uint32_t& x){return x*=100;}); } inline void print() { boost::copy(b,std::ostream_iterator<std::uint32_t>(std::cout," ")); } int main() { init(); __asm__ ( "vmovdqa32 (%0), %%zmm0;" "vpaddd (%1),%%zmm0,%%zmm0;" "vmovdpa32 %%zmm0, (%2);" ::"a"(a), "b"(b), "c"(result) ); print(); }
__asm__
中のvmovdqa32
、vpaddd
がAVX512命令である。さて、これを例えば何もコンパイルオプションを指定せずにコンパイルすると以下のようなエラーが出力される。
t.cpp:31:4: error: instruction requires: AVX-512 ISA "vmovdqa32 (%0), %%zmm0;" ^ <inline asm>:1:2: note: instantiated into assembly here vmovdqa32 (%rax), %zmm0;vpaddd (%rbx),%zmm0,%zmm0;vmovdpa32 %zmm0, (%rcx); ^ t.cpp:31:4: error: instruction requires: AVX-512 ISA "vmovdqa32 (%0), %%zmm0;" ^ <inline asm>:1:26: note: instantiated into assembly here vmovdqa32 (%rax), %zmm0;vpaddd (%rbx),%zmm0,%zmm0;vmovdpa32 %zmm0, (%rcx); ^ t.cpp:31:4: error: invalid instruction mnemonic 'vmovdpa32' "vmovdqa32 (%0), %%zmm0;" ^ <inline asm>:1:52: note: instantiated into assembly here vmovdqa32 (%rax), %zmm0;vpaddd (%rbx),%zmm0,%zmm0;vmovdpa32 %zmm0, (%rcx); ^~~~~~~~~ 3 errors generated.
まあ当然なのだが、エラー文からも正しくAVX512命令を下せている事が確認できる。さて、オプションを指定して、動かす。
% $MPX_GCC/bin/g++ -fcheck-pointer-bounds -mmpx -L$MPX_RUNTIME_LIB -B$MPX_BINUTILS/bin -lmpx-runtime64 -Wl,-rpath,$MPX_RUNTIME_LIB -std=c++1z t.cpp
と思いきや、sys/cdefs.hがないという旨が。libc6-dev-i386というパッケージに含まれているので、インストール。
% sudo apt install libc6-dev-i386
再度実行。
$ sde64 -- ./a.out 0 101 202 303 404 505 606 707 808 909 1010 1111 1212 1313 1414 1515
...という事である程度遊んでみたわけだが、実際の実機でこの命令を動かせるようになるのは、一体いつになるのやら。
Xeon Phiと最適化に纏わるコンパイラなどの情報
本セミナーで得たXeon Phiの特徴とそれを活かしたコードを動かすためのコンパイラ対応情報など。 以下に示されている内容は本セミナーで私がヒアリングした内容を書き出したものなので、厳密な情報を求める場合は規格書や公式のリファレンスガイドなどを参照すべし。
- インテルXeon Phi プロセッサーが装備されたマシンでは一般的なOSを起動可能(セミナーでは一般的なCentOSが動いていた)
- Xeon Phiは、3つのMCDRAM(Xeon Phi内蔵)メモリーモードを起動時にBIOS設定に準じて選択する
* キャッシュモード:自動的な利用。排他制御などはOS側管理 * フラットモード:MCDRAMが見える。それを使い分けるために、実行時またはプログラムコード内でその旨の最適化?attribute的なものを書く必要がある * ハイブリットモード:上記二つの両方。一部を割り当て可能なメモリとしたり。
- 様々なクラスターモード
* sub-NUMA Clusteringを除くすべてはソフトウェア側から見えない(自動制御) * sub-NUMA Clusteringでは明示的に記述する(NUMA対応)
- コンパイラ対応
* インテルコンパイラ 15.0以降 * GCC 4.9.1(binutils 2.24)以降 * option:-mav512f -mavx512cd -mavx512er -mav512pf
- 競合検知拡張命令(AVX512-CD)はXeon 6から。コンパイラは対応している。
- MCDRAMを利用するには:
* コマンドによる割り当て、AutoHBWライブラリによる半自動化 * memkind ライブラリで利用
関連ツイート
Xeon phiのセミナー、Parallel computingに関して言えば基礎的なライブラリの紹介に留まった。TBBとかの突っ込んだ話してくれるのかと思ったけど。
— roκi (@530506) 2017年1月20日
AVX512命令の話がやはり盛り上がった。特にAVX512-CD。競合検知によって全てのSIMD演算を断念せずに済むとは、アツいな。ローレベルなはずなのに抽象化の技術が見えて境界線がよーわからなくなる。
— roκi (@530506) 2017年1月20日
手元にあるマシンでAVX512命令を実現するためにはカーネルがSIGILL飛ばす前にフックしてAVX512と同処理の動作させるようにカーネル変えるしかないのかと思ってたけど公式のエミュレータがあった。
— roκi (@530506) 2017年1月20日
後これ頂きました。ありがとうございます。 pic.twitter.com/uuc2C7rMxj
— roκi (@530506) 2017年1月20日
Intel Code Modernization 2017は30人前後の収容人数で、小休憩を10分挟んで合計2時間程、最新のIntelプロセッサー、Xeon Phi搭載マシンの情報と、それに対する適したプログラミングスタイルを説明するといった内容。個人的には、スライド資料がとてもよく纏まっており、分かりやすく感じた。*3
最後のツイートの書籍は、近頃日本語訳された書籍*4が販売されるそうだ。折角無償で頂いたので、英書籍を読む事にする。