Rokiのチラ裏

学生による学習のログ

Intel Code Modernization 2017に参加した

Intel Code Modernization 2017に参加した。Intel流のParallel Computingについての情報やそれに対する知見を得た。その際に個人的に印象深かったAVX512命令であるが、当然ながら今現在でその命令に完全対応したコンシュマー向けのアーキテクチャは存在しない*1。 しかし、エミューレータがあるというお話だったので、手元のマシンでも命令を動かして見る事にした。*2

現代のマシンでAVX512命令をエミュレートする遊び

エミュレータWindowsLinuxに対応しているようだが、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からGCCGDBをダウンロードする。

% 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__中のvmovdqa32vpadddが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 ライブラリで利用
    

関連ツイート

Intel Code Modernization 2017は30人前後の収容人数で、小休憩を10分挟んで合計2時間程、最新のIntelプロセッサー、Xeon Phi搭載マシンの情報と、それに対する適したプログラミングスタイルを説明するといった内容。個人的には、スライド資料がとてもよく纏まっており、分かりやすく感じた。*3

最後のツイートの書籍は、近頃日本語訳された書籍*4が販売されるそうだ。折角無償で頂いたので、英書籍を読む事にする。

*1:Xeon Phiでは動く

*2:MCDRAMのメモリーモードごとの挙動の変化なども自分の手で動かして遊んで見たいところだが、流石に実機が必要なので、残念ながら不可能。

*3:紙媒体でスライド資料を貰えるので、後に見直す事ができる。

*4:8k前後?のお値段