iRICのソルバーのコンパイルにifortではなくifxを使用したらiRIC上で動かなかった話

# はじめに
色々試行錯誤して一応どうにか動いたので備忘録としてメモします。

## ざっくり結論
結論としてはiRIC.exeの入っているフォルダ（iRIC_v4\guis\prepost）に[Intel® Fortran Compiler Runtime](https://www.intel.com/content/www/us/en/developer/articles/tool/compilers-redistributable-libraries-by-version.html)でインストールしたランタイムdllを入れたらiRIC上でも動くようになった。

ただしこの方法が正しいかはよくわからないので自己責任で。
背景等は読む必要がないので解決法だけ知りたい人は [一応解決した方法](#一応解決した方法) へ。

# 背景

普段、fortranで書かれたiRICのソルバーのコンパイルには以下の記事を参考に導入したIntel® Fortran Compiler Classicを使用していて、導入した当時は特に何も考えずに使用できていた。

https://qiita.com/Kazutake/items/a069f86d21ca43b6c153

当時Visual Studio2022でうまくコンパイルできなかったのでVisual Studio2019を使用していたのだが、アップデートで直ったようなので、先日Visual Studio2022と合わせてIntel oneAPI Base ToolkitとIntel oneAPI HPC Toolkitをアップデートしたことがこの話の始まり。

## Intel® Fortran Compiler Classic (ifort)が廃止になる

アップデートして試しにifortでコンパイルしてみたところ以下のようなメッセージが表示された。
読むにIntel® Fortran Compiler Classic (ifort)が2024年末に廃止になるからIntel® Fortran Compiler (ifx) 使ってねってことらしい。知らなかった。

> ifort: remark #10448: Intel(R) Fortran Compiler Classic (ifort) is now deprecated and will be discontinued late 2024. Intel recommends that customers transition now to using the LLVM-based Intel(R) Fortran Compiler (ifx) for continued Windows* and Linux* support, new language support, new language features, and optimizations. Use '/Qdiag-disable:10448' to disable this message.
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.12.0 Build 20240222_000000
Copyright (C) 1985-2024 Intel Corporation.  All rights reserved.

参考：

https://www.xlsoft.com/jp/blog/intel/2023/12/19/deprecation-of-the-intel-fortran-compiler-classic-ifort/


なのでifxでコンパイルしてみたらexeがiRIC上で動かなくなって困ったという話です。ちなみにifortでビルドしたexeはiRIC上でも普通に動いた。

# 状況

使用環境
| ソフト | Version |
|:-|:-|
| Microsoft Visual Studio Community 2022  | 17.9.5  |
| Intel oneAPI Base Toolkit  | 2024.1  |
| Intel HPC Toolkit  | 2024.1  |
| Intel® Fortran Compiler  | 2024.1.0  |
| Intel® Fortran Compiler Classic | 2021.12.0 |


* Visual Studio2022上で動かす場合、普通に動いた
* Visual Studio2022で「 構成のプロパティ > Fortran > Libraries > Runtime Library」で`Multithreaded`か`Debug Multithreaded (/libs:static /threads /dbglibs)`にしてビルドしたexeはiRIC上でも動く([こちら](https://www.rccm.co.jp/icem/pukiwiki/index.php?for_stop_core_quiet%E3%82%A8%E3%83%A9%E3%83%BC)を参考にした)
     ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2626673/9cdb1084-7b04-e9bd-aabe-dceb3e139d62.png)
* コマンドラインでifortを使用してビルドしたexeもiRIC上で普通に動く

## batファイルからifxでビルドしたexeがiRIC上で動かない

普段batファイルを使ってコマンドラインでビルドしているので、今回も同様にコマンドラインでifxを使ってビルドを行ったところiRIC上でexeが動かなかった。
実際のbatは以下。

```batch:make.bat
@echo off

call "C:\Program Files (x86)\Intel\oneAPI\setvars.bat" intel64 vs2022

rem ----------------------------------------------------------------------
rem ifort compile
rem ----------------------------------------------------------------------
ifx .\src\iric.f90  /Qopenmp /nostandard-realloc-lhs /MD /c
ifx .\src\Grid_tester.f90  /Qopenmp /nostandard-realloc-lhs /MD /c
ifx *.obj ^
      .\lib\iriclib.lib ^
      -o ".\install\Grid_tester.exe"

del *.obj
del *.mod
```

### for_alloc_allocatable_handl ダイナミックリンクライブラリが見つからない

上記の内容でビルドしたexeをiRIC上で実行すると「プロシージャエントリポイント for_alloc_allocatable_handl がダイナミックリンクライブラリ　～　から見つかりませんでした。」と言われソルバーが異常終了してしまう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2626673/6779927d-c3ca-8500-f89a-18fe8e3d260e.png)

Intel® Fortran Compiler (ifx) のランタイムdllがある場所にはPATHを通してあったがどうも認識されていないよう。どのdllが必要なのかもよくわからない。

### __kmpc_aligned_alloc ダイナミックリンクライブラリが見つからない

それならば静的リンクにしてしまえということで、ビルド時のオプションを`/MD`から`/MT`に変更した。

https://www.intel.com/content/www/us/en/docs/fortran-compiler/developer-guide-reference/2024-1/md.html

https://www.intel.com/content/www/us/en/docs/fortran-compiler/developer-guide-reference/2024-1/mt.html

for_alloc_allocatable_handlは無事に見つかったようだが、今度は__kmpc_aligned_allocが見つからないと言われた。PATHは通してあるはずなのに見つからないものだらけである。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2626673/fa63ffed-ac0b-2ca7-ff80-b6a7714cb11b.png)

ちなみにこれは`libiomp5md.dll`が原因っぽい
これが入っているifxのランタイムDLLのある`C:\Program Files (x86)\Intel\oneAPI\compiler\latest\bin`にPATHは通っているのに。。。。

### 類似の事例

そう言えば同様の問題を見たことがあると思ったら以下の記事だった。
最終的にバッチファイルからソルバーを実行しているが、iRIC上から実行するのは無理なのだろうか。

https://qiita.com/Kazutake/items/bc03f6fca3dea80870b8

# 一応解決した方法

どうにもならないので某iRIC開発者に助言を求めたところ以下の回答を頂いた。
* iRICにはIntel® Fortran Compiler Classic (ifort)のランタイムDLLは同梱している
* だがはIntel® Fortran Compiler (ifx)のランタイムDLLは同梱していない
* iRIC.exeと同じフォルダにifxのランタイムDLLを置けば動くはず

ということでifxのランタイムDLLを`iRIC_v4\guis\prepost`に入れてみる。


## Intel® Fortran Compiler (ifx)のランタイムDLLを探す
ifxのランタイムDLLは[Intel oneAPI Base Toolkit](https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit.html)と[Intel HPC Toolkit](https://www.intel.com/content/www/us/en/developer/tools/oneapi/hpc-toolkit-download.html)をインストールしていれば`C:\Program Files (x86)\Intel\oneAPI\compiler\latest\bin`に入っている。

https://www.intel.com/content/www/us/en/developer/tools/oneapi/base-toolkit.html

https://www.intel.com/content/www/us/en/developer/tools/oneapi/hpc-toolkit-download.html


または[Intel® Fortran Compiler Runtime for Windows](https://www.intel.com/content/www/us/en/developer/articles/tool/compilers-redistributable-libraries-by-version.html)でランタイムパッケージだけをインストールしている場合は`C:\Program Files (x86)\Common Files\intel\Shared Libraries\bin`に入っている。自分でコンパイルしない人はこっちで十分。

https://www.intel.com/content/www/us/en/developer/articles/tool/compilers-redistributable-libraries-by-version.html

## iRIC_v4\guis\prepostにランタイムDLLをコピーする

先ほど探したランタイムDLLをiRIC.exeが入っている`iRIC_v4\guis\prepost`にコピーする。

何かあってもiRICを再インストールすれば問題ないが、めんどくさいのでprepostを丸ごとバックアップとっておきましょう。

私の環境では以下のファイルが既にあると言われましたが上書きでいいです。

```
tbbmalloc_proxy.dll
tbbmalloc.dll
tbbbind_2_5.dll
tbbbind_2_0.dll
tbbbind.dll
tbb12.dll
svml_dispmd.dll
onnxruntime.1.12.22.721.dll
libmmdd.dll
libmmd.dll
libiomp5md.dll
libifportmd.dll
libifcorertd.dll
libifcorert.dll
libifcoremdd.dll
libifcoremd.dll
```

コピー後にiRICを起動して実行してみたらうまく動きました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2626673/bb8bec66-6147-9f65-a75a-04617ee71a14.png)

# まとめ

* iRIC.exeのあるフォルダに必要なDLLを置けば動く
* **自己責任でお願いします**

# 参考リンク集

https://www.xlsoft.com/jp/blog/intel/2023/12/19/deprecation-of-the-intel-fortran-compiler-classic-ifort/

インテル® Fortran コンパイラー クラシックおよびインテル® Fortran コンパイラー開発者ガイドおよびリファレンス

https://www.intel.com/content/www/us/en/docs/fortran-compiler/developer-guide-reference/2024-1/overview.html

インテル® Fortran コンパイラー移植ガイド

https://www.intel.com/content/www/us/en/developer/articles/guide/porting-guide-for-ifort-to-ifx.html

インテル® Fortran コンパイラー クラシックおよびインテル® Fortran コンパイラー開発者ガイドおよびリファレンス

https://www.intel.com/content/www/us/en/docs/fortran-compiler/developer-guide-reference/2024-1/overview.html

アルファベット順オプションリスト

https://www.intel.com/content/www/us/en/docs/fortran-compiler/developer-guide-reference/2024-1/alphabetical-option-list.html

# 独り言

あってるのかどうかもわからないけど自分なりの今回の解釈

ifxのランタイムDLLがあるフォルダにPATH通していたのに動かなかったのは、iRICに同梱されているifortの古いランタイムDLLが先に読み込まれていたから？

DLLの読み込み優先度について、下記リンクの記事を読むに、明らかにiRIC.exeのあるフォルダのほうが優先度が高いので十分ありえる。

https://learn.microsoft.com/ja-jp/windows/win32/dlls/dynamic-link-library-search-order#standard-search-order-for-unpackaged-apps

DLLのバージョンについて、ifortとifxは一応互換性あるらしいですが、iRICに同梱されたDLLが古かったり足りなかったのでしょうか。
そう言えば__kmpc_aligned_allocで問題になっていた`libiomp5md.dll`は元々iRICに同梱されていたが、同梱されていたものはバージョンが`5.0.2020.1007`で、今回コピーしたものは`5.0.2023.1212`なので確かに古かった。

今回ビルドに使ったifxのバージョンは最新の`2024.1.0`、それに対してifortは最新版でも`2021.12.0`、iRICに同梱されているランタイムがどのバージョンのifortのものかはわからないが、ifortのランタイムという時点でifxで使用しているランタイムより古いというのは納得できる。

なるほど、どうりでPATHを頑張って通したりしてもうまくいかなかったわけですね。