Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ランタイム CDLL ロードの仕組み #1146

Closed
tarepan opened this issue Mar 26, 2024 · 8 comments
Closed

ランタイム CDLL ロードの仕組み #1146

tarepan opened this issue Mar 26, 2024 · 8 comments

Comments

@tarepan
Copy link
Contributor

tarepan commented Mar 26, 2024

質問の内容

質問概要: ランタイム CDLL ロードの仕組みが知りたい

現在の ENGINE は load_runtime_lib() においてランタイム CDLL (例: onnxruntime.dll) をロードしている。

CDLL(str((lib_path / file_name).resolve(strict=True)))

この CDLL は純粋にロードのみがなされ、ENGINE 内ではその後明示的に利用されていない。
CORE 側の仕組みによって上手く利用されていると想定されるが、その挙動は ENGINE 的には不明である。

#709#1133 でランタイム CDLL の読み込み方式が論点となっているが、議論の前提としてこの仕組みの理解が必要となっている。

このような背景から、次の質問があります:

「ランタイム CDLL はロードされたのちどのように選択・利用されるのか」

ENGINE コントリビュータからすると CORE の理解は相当なハードルがあります。
可能であれば CORE 側のランタイムロード関連の仕組みについて簡単な解説があると非常に助かります。
もしご多忙でしたら、読むべき CORE 側のコードを示して頂ければ幸いです。

詳しそうな方々: @Hiroshiba @qryxip

VOICEVOXのバージョン

0.18.0

@tarepan tarepan added the 要議論 実行する前に議論が必要そうなもの label Mar 26, 2024
@qryxip
Copy link
Member

qryxip commented Mar 28, 2024

私の理解では例えばonnxruntime.dllは、voicevox_core.dllのロード時点で

  1. 解決可能か
  2. 既にロードされている

必要があります。1.だとWindows上では難しいため、2.とするためにCDLL、すなわちdlopen/LoadLibraryでonnxruntime.dllを読み込んでいます。

もし1.でも2.でもない場合、Linuxの場合はlibvoicevox_core.soのロード時にこのようになるはずです。

OSError: libvoicevox_core.so: cannot open shared object file: No such file or directory

メッセージとしてはCOREのPyO3版でimport voicevox_coreしたときの方がわかりやすいかもしれません。libonnxruntime抜きでimport voicevox_coreするとこうなります。

ImportError: libonnxruntime.so.1.14.0: cannot open shared object file: No such file or directory

Windowsの場合は2.でない限り、強制的にC:\Windows\System32\onnxruntime.dllが解決されてしまい人間にはわかりにくいエラーになります

(追記) 複数をロードした場合順番は…どうでしょうね。dlopen (Unix)とLoadLibrary (Windows)で違うことすらありうるかも。

@qryxip
Copy link
Member

qryxip commented Mar 28, 2024

今後の話ですが、VOICEVOX/voicevox_core#721ができるとlibvoicevox_core → libonnxruntimeの依存の関係が通常の動的リンクからdlopen/LoadLibraryに変わるため、CORE側で自分ですべてなんとかすることができるようになります。そうなったらENGINE側での対処は無くてもよいし、有っても問題は起こさないと思います(RTLD_LOCAL相当のはずなので)。なのでload_runtime_lib()は≦0.15のコアとDirectML版コアのための処理になると思います。

さらにVOICEVOX/voicevox_core#721を達成すると、依存DLLがonnxruntime.dllからvoicevox_onnxruntime.dllに代わります。

今のところコアは、上記二つとも行った上でリリースする予定です。

@tarepan
Copy link
Contributor Author

tarepan commented Mar 28, 2024

@qryxip
丁寧にありがとうございます、非常に助かります!
onnxruntime.dll がパス解決可能 or プロセスにロード済みじゃないと CORE ロード時に落ちる」があり、そのために ENGINE 側で事前ロードしているということですね。

現実装でのCORE ロード時についてなのですが、onnxruntime.dll へ直接アクセスを試みるのは CORE でしょうか、それとも依存している https://github.com/VOICEVOX/onnxruntime-rs でしょうか?
複数ロード等の理解のために onnxruntime.dll アクセス箇所(落ちうるポイント)を探したのですが、CORE に見当たらない…?となりまして。

@qryxip
Copy link
Member

qryxip commented Mar 29, 2024

強いて言うならビルド時に実行されるここでしょうか。onnxruntime.dll側の各関数シンボルを宣言し、それらの解決をonnxruntime.dllで行うように指示、というのをonnxruntime-sys (onnxruntime-rs)はビルド時にやっているという理解です。
https://github.com/VOICEVOX/onnxruntime-rs/blob/7d9eeedf4c39cee965c0385cf8601d9392b62cde/onnxruntime-sys/build.rs#L132-L134

@tarepan
Copy link
Contributor Author

tarepan commented Mar 29, 2024

それらの解決をonnxruntime.dllで行うように指示、というのをonnxruntime-sys (onnxruntime-rs)はビルド時にやっている

まさにこのコードが知りたい箇所の1つでした、ありがとうございます!

  • onnxruntime 名で実行時に DLL アクセスしろ」との指示で onnxruntime-sys がビルド
  • 実行時に onnxruntime-sys 内で DLL アクセス実行
  • 見つからないと cannot open shared object file になったり、Win で build-in onnxruntime に解決されたり

という感じですかね。

多重ロード時の実動作

#1133 で議題になった多重ロード時の実動作に関して。

上記の情報に基づくと「CORE 側でロード順を制御してる」というより「Python ctypes の CDLL 複数回コール時挙動で実動作が左右される」が妥当そうに見えます。
(なのでCORE 側の挙動に関する質問 issue である本 issue は close 可能かも。)
CDLL 周りの情報持っている方のアドバイスが頂ければ幸いです。

@tarepan
Copy link
Contributor Author

tarepan commented Mar 29, 2024

(Discord から情報転記)

#254 等を深堀り)

@tarepan
Copy link
Contributor Author

tarepan commented Apr 6, 2024

Python ctypes の CDLL 複数回コール時挙動は以下の形と推定されます(情報転記):

同名のライブラリを複数読み込んだ場合の挙動は、一番初めに読み込んだものを使うようになっているようです。
https://ikb.hatenablog.com/entry/20110830/1314684440
そのため、現在の挙動としては、
--runtime_dir--voicevox_dirもしくはengine_root
の順でディレクトリ内を検索し、先に見つかったものが使われるのではないかと思います。
(それでも見つからない場合は、ctypes.util.find_libraryの検索結果が使われる)
takana-v. (2024). #1148 (comment)

@tarepan
Copy link
Contributor Author

tarepan commented Apr 6, 2024

CORE 側の DLL 利用方法および Python 側の DLL 多重ロード挙動が理解されたため、本 issue は resolve につき close とします。

@tarepan tarepan closed this as completed Apr 6, 2024
@tarepan tarepan removed the 要議論 実行する前に議論が必要そうなもの label Apr 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants