CMakeでIntel MKLをリンクする

## はじめに
　CMake[^cmake]でIntel MKL[^mkl]を利用する方法をまとめる．本記事は前記事[CMakeに関する個人的メモ](https://qiita.com/toya42/items/13ef8a6cd45af2aeb41d)の内容を補うものである．

[^cmake]: CMake 公式webサイト (https://cmake.org/)
[^mkl]: Intel® Math Kernel Library, webサイト: https://software.intel.com/en-us/mkl , EULA: https://software.intel.com/en-us/articles/end-user-license-agreement


## 手順 

1. Intel® Math Kernel Library Link Line Advisor[^intellink]を用いて，環境と要求に合ったコマンドラインを調べる．
2. 必要なincludeファイルを`add_executable`に併記する
3. 必要なライブラリを`target_link_libraries`で指定する．

### 例1 : FFTの利用

　`mkl_dfti.f90`を`add_executable`に併記する．`${MKLROOT}`は筆者の環境では（macでもUbuntuでも）`/opt/intel/mkl/`以下であった．

```cmake
add_executable(${EXECUTABLE}
    main.F90
    ${MKLROOT}/include/mkl_dfti.f90
)
```

　必要なライブラリを追加．

```cmake
target_link_libraries(${EXECUTABLE}
    PRIVATE
# Intel Link Advisor
# https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor

# 32-bit integer
    mkl_intel_lp64
# 64-bit integer
#    mkl_intel_ilp64

# OpenMP threading
    mkl_intel_thread
# Sequential
#    mkl_sequential
    
    mkl_core
)
```

`make`された実行ファイルについて`ldd`コマンドで共有ライブラリを調べると，

```
libmkl_intel_lp64.so libmkl_intel_thread.so libmkl_core.so
```

が見えるはずである．

macでは，`otool -L`コマンドを用いれば

```
libmkl_intel_lp64.dylib libmkl_intel_thread.dylib libmkl_core.dylib
```

が確認できる．

### 例2 : 静的ライブラリの利用

　例1では，ライブラリ名のみを記述すると共有ライブラリがリンクされることがわかった．静的ライブラリを利用したい場合はフルパスでライブラリを記述する．加えて，Linux環境では`-Wl,--start-group`と`-Wl,--end-group`で囲む．次は，Linux環境でLAPACK95インターフェースを用いた場合の例である．

```cmake
add_executable(${EXECUTABLE}
    main.F90
    ${MKLROOT}/include/lapack.f90
)

target_link_libraries(${EXECUTABLE}
    PRIVATE
    -Wl,--start-group
    ${MKLROOT}/lib/mkl_lapack95_lp64
    ${MKLROOT}/lib/libmkl_intel_lp64.a
    ${MKLROOT}/lib/libmkl_intel_thread.a
    ${MKLROOT}/lib/libmkl_sequential.a
    ${MKLROOT}/lib/libmkl_core.a
    -Wl,--end-group
)
```

### 例3 : GFortranでの利用

上の2例はifortの使用を想定していた．現在Intel MKL[^mkl]は無償で使用が可能である．Link Line Advisorに従えば，GFortranを用いる場合に必要なライブラリも簡単に調べられる．

```cmake
target_link_libraries(${EXECUTABLE}
    PRIVATE
    mkl_gf_lp64
#    mkl_gnu_thread
    mkl_sequential
    mkl_core
)
```

### 例4 : 大規模配列の利用

$2^{31}-1$以上の要素を持つ配列を利用する場合，`mkl_intel_lp64`ではなく`mkl_intel_ilp64`ライブラリを利用する．かつコンパイルオプションに`-i8`を追加する．



## Link Line Advisorが表示するその他のコンパイルオプション

　Link Line Advisorを使用すると，上記のMKL関連ライブラリに加えて，いくつかのライブラリをリンクするように指示してくる．例えば，`-liomp5 -lpthread -lm -ldl`である．これらを明記しなくても（現状筆者の環境では）プログラムは正常に実行される．

* `-liomp5`あるいは`lgomp`

OpenMP関連だが，[前の記事](https://qiita.com/toya42/items/13ef8a6cd45af2aeb41d)に示したように以下のように書けば，適切なOpenMPライブラリとリンクされる．つまりGFortranなら`-lgomp`，ifortなら`-liomp5`等と書き分ける必要はない．

```cmake
find_package(OpenMP REQUIRED)

#~~~~~

target_link_libraries(${EXECUTABLE}
    PRIVATE
#~~~~~
# OpenMP threading
###  for ifort
    mkl_intel_thread
### for gfortran
#    mkl_gnu_thread
    OpenMP::OpenMP_Fortran
  )
```

* `-lpthread`

`libpthread`はPOSIXスレッドライブラリで，"言語に依存せず主にtaskレベルの並列化に用いられる"[^posix]との事で，OpenMPとの併用が可能なようだ．しかし，"OpenMPの命令文を用いる方がより簡潔"[^posix]で，"コーディングとデバッグが困難"[^posix]とまで書かれている．
　自分の書いたコードで利用していなくても，Link Line Advisorが指定しているということは，MKL内部でこれを利用しているのかもしれない．一応このオプションはつけておく方が無難ではないだろうか．

* `-lm`

`libm`は数学ライブラリだが，コンパイル時に次のような警告が出る場合がある．

```
ifort: warning #10315: 
specifying -lm before files may supersede the Intel(R) math library and affect performance
```

この警告メッセージのみを見る限り，このオプションはつけない方が良いと思われる．

* `-ldl`

`libdl`でいろいろ検索してみたが，正直よくわからない．IBMの[Linux 動的ライブラリーの徹底調査](https://www.ibm.com/developerworks/jp/linux/library/l-dynamic-libraries/index.html)という記事によれば動的ロード(dynamic loading)のためのアプリケーション・プログラム・インターフェース (API) らしい．

## 終わりに
　とりあえず，[前の記事](https://qiita.com/toya42/items/13ef8a6cd45af2aeb41d)と合わせて，自身が使うための一通りの知識を得られた．「CMakeでIntel MKLを利用する方法をまとめる」ことはできたが，MKLのためのいくつかのコンパイルオプションについてはまだ疑問が残っている．わかり次第追記したい．


[^intellink]: Intel® Math Kernel Library Link Line Advisor https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor
[^intelmkl]: webサイト: https://software.intel.com/en-us/mkl , EULA: https://software.intel.com/en-us/articles/end-user-license-agreement
[^posix]: Threading Fortran Applications for Parallel Performance on Multi-Core Systems,（本文中の""内の文章はこのページの英文を意訳したものである） https://software.intel.com/en-us/articles/threading-fortran-applications-for-parallel-performance-on-multi-core-systems