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

Rust化の追従をしていく #213

Open
10 of 17 tasks
Hiroshiba opened this issue Aug 6, 2022 · 36 comments
Open
10 of 17 tasks

Rust化の追従をしていく #213

Hiroshiba opened this issue Aug 6, 2022 · 36 comments

Comments

@Hiroshiba
Copy link
Member

Hiroshiba commented Aug 6, 2022

内容

#128 の追従タスクを一覧化します。

  • windowsでDLLコピーせずに動くようにする
  • 動くことを確認する
    • windows DirectML
    • windows GPU
    • linux GPU
    • linux
    • mac
  • macのuniversalビルド
  • linuxのarmhfビルド ref
  • エンジン側のビルド機構書き換え
  • configure.pyの追従(onnxruntimeのダウンロードをなくすとか)
  • forward_*の出力が以前と同じになっていることを確認する
  • TTS出力がエンジンの出力と同じになっていることを確認する
  • Rustブランチを削除する

その他

確認等できたらコメントをお願いします!

@qwerty2501
Copy link
Contributor

Windows上でcargo testするとエラーになる件issue作りました VOICEVOX/onnxruntime-rs#3

@qwerty2501
Copy link
Contributor

そういえばopen_jtalkの辞書読み込み時のpathをutf8に変更した影響がengine側に出てるかもですね

@Hiroshiba
Copy link
Member Author

Hiroshiba commented Aug 7, 2022

あ~~忘れていました。こちらですね。一覧に書き足します。

@Hiroshiba
Copy link
Member Author

合成結果が以前と同じかどうかをチェックしないとなので、ちょっとタスクを足しました。

@PickledChair
Copy link
Member

https://github.com/VOICEVOX/voicevox_core/releases/tag/0.13.0-rust.0 で配布されている製品版コアについて、macOS において

  • unix example の実行
  • voicevox_engine での利用 (--voicelib オプションで指定する)

がうまくいくことを確認しました!

@Hiroshiba
Copy link
Member Author

windows版Rustコア試してみました!
CPU版とCUDA版は正しく動作していそうでした!

windows DirectMLを試したところ、おそらくGPUを使わずに生成しているっぽい挙動をしていました。
VOICEVOX DirectML zip版のcore.dllとonnxruntime.dllをRust版コアに入れ替えて、GPUモードで生成した感じ、CPU使用率が高まる感じでした。
おそらくGPUを持っていない人でもDirectML版GPUで生成できるはず・・・?

@qwerty2501
Copy link
Contributor

C++版と挙動が違うってことですかね?

@qryxip
Copy link
Member

qryxip commented Aug 9, 2022

LinuxのCPU版は動きました(GPU版はC++版もSEGVする状態だったので確認できていません)

@Hiroshiba
Copy link
Member Author

C++版と挙動が違うってことですかね?

ですです!
DirectML版でGPUモードで長い文章を生成するとGPUメモリ使用量と使用率が上がるのですが、その挙動がなく代わりにCPUが使われるといった感じです!

@qwerty2501
Copy link
Contributor

qwerty2501 commented Aug 10, 2022

@Hiroshiba RustのDirectMLでCPU使用率が上がる件これが関係してるかもです

#227 (comment)
ただ、GPU使用率が全く上がってない状態であれば原因は別にありそうですが

@qwerty2501
Copy link
Contributor

qwerty2501 commented Aug 10, 2022

改めてコード見た感じだとRust版はこれが抜けてるようなのでそれが原因かも
https://github.com/VOICEVOX/voicevox_core/blob/0.12.5/core/src/core.cpp#L98
ただこれ、 dml_provider_factory.h というヘッダーに定義されてるものでいまのonnxruntime-rsにはないものでコード生成から作らないといけなさそうです

@qryxip
Copy link
Member

qryxip commented Aug 10, 2022

LinuxのGPUですが、古いlibonnxruntime_providers_{cuda,shared}.soを読んでいただけだったのでORT 1.11.1のに入れかえたら普通に動きました。

#227 (comment)

@Hiroshiba
Copy link
Member Author

検証ありがとうございます!
認識合ってるか確認なのですが、core.zipにはlibonnxruntime_providers_*.soも一緒に配布したほうが良いって感じで合ってそうでしょうか 👀

@qryxip
Copy link
Member

qryxip commented Aug 10, 2022

はい。coreのリリースにはWindows版と同様にlibonnxruntime_providers_*.soを同梱した方がよいと思います。

@qwerty2501
Copy link
Contributor

windowsでDLLコピーせずに動くようにする

これは解決したはず

@sevenc-nanashi
Copy link
Member

0.13.0-rustで動作確認してきました。
句読点が無視されてそう。
エディタ生成
コア生成

コア生成のコードはこれです。雰囲気で読めると思います。
https://github.com/sevenc-nanashi/voicevox.rb/blob/main/examples/repl_core.rb

また、複数回生成させるとバグりました。(initialize->voicevox_tts->voicevox_tts)
自分のFFI実装が間違ってる可能性もあります。
https://cdn.discordapp.com/attachments/893889888208977960/1007930899939201074/163828_2.wav

== 初期化中... 完了
> 同じ、文章、です。完全に、同一です。
生成中... 完了:144940バイト、アドレス:3c925f68
> 同じ、文章、です。完全に、同一です。
生成中... 完了:415276バイト、アドレス:e8eed00

@qwerty2501
Copy link
Contributor

qwerty2501 commented Aug 13, 2022

Rust側のテストコードでも確認しました。なんかサイズが増えているっぽい?

    #[rstest]
    #[async_std::test]
    async fn voicevox_tts_loop_works() {
        let internal = Internal::new_with_mutex();
        internal.lock().unwrap().initialize(false, 0, true).unwrap();
        let open_jtalk_dic_dir = download_open_jtalk_dict_if_no_exists().await;
        internal
            .lock()
            .unwrap()
            .voicevox_load_openjtalk_dict(open_jtalk_dic_dir.to_str().unwrap())
            .unwrap();
        let text = "同じ、文章、です。完全に、同一です。";
        let first_tts_wav = internal.lock().unwrap().voicevox_tts(text, 1).unwrap();
        assert_ne!(0, first_tts_wav.len());

        for i in 0..3 {
            let wav = internal.lock().unwrap().voicevox_tts(text, 1).unwrap();
            assert_eq!(first_tts_wav.len(), wav.len(), "index:{i}");
        }
    }

結果

> cargo test -- voicevox_tts_loop_works
   Compiling voicevox_core v0.1.0 (/home/qwerty2501/projects/qwerty2501/voicevox_core/crates/voicevox_core)
    Finished test [unoptimized + debuginfo] target(s) in 6.15s
     Running unittests src/lib.rs (target/debug/deps/core-0c73abe9c87fb1c8)

running 1 test
test internal::tests::voicevox_tts_loop_works ... FAILED

failures:

---- internal::tests::voicevox_tts_loop_works stdout ----
-------------- TEST START --------------
thread 'internal::tests::voicevox_tts_loop_works' panicked at 'assertion failed: `(left == right)`: index:0

Diff < left / right > :
<164396
>477740

', crates/voicevox_core/src/internal.rs:747:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    internal::tests::voicevox_tts_loop_works

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 72 filtered out; finished in 6.58s

@qwerty2501
Copy link
Contributor

ちょっとconfigure.pyについて考えていることがあるのでコメントに残しておきます

  1. configure.py修正前にreleasesにcuda,directmlの全部入り版のzipも提供するようにしたほうが良いと思います。そうすればconfigure.pyの処理は指定したものをダウンロードして展開するだけになるので処理の簡略化ができますし、configure.pyを使わない人に対しても環境を用意する手間を省けるようにできます。
  2. 1に対応してreleasesでダウンロードするだけで良くなった場合、configure.pyは必要なのだろうか?とちょっと思ってます。またダウンロード用のscriptを提供するにしてもpythonが環境にない人のためにunix系はsh, Windowsにはpowershellのスクリプトを提供したほうが良いのではないでしょうか。2つスクリプトをメンテする必要が出てきますが、1に対応していればダウンロードしてファイル展開する程度の処理なのでそこまでメンテ性が悪くないと思います。特にWindowsについてはpythonをインストールしていない人はそれなりにいると思いますので

@Hiroshiba
Copy link
Member Author

Hiroshiba commented Aug 14, 2022

提案ごもっともだと思います。手軽に使えるようにするためには、エンジンやエディタと同様に、全部入りを配布するのが手っ取り早いと思います。

cuda,directmlの全部入り版のzip

releasesに載せられるファイルの最大である2GBを超す可能性があり、分割が必要で結構リリースが複雑になります。
実際linuxのエンジンは1GBごとに分割してリリースしています。

discordでは避けたい旨を伝えたかもですが、7zにして配布すればそこまで手間ではないかもと思いました!

追記:あ、でもディストリビューションごとに×3個とかになると、releasesに大量にファイルが並んで結局使い勝手が落ちるかもですね・・・。
ダウンロードスクリプトのほうが使い勝手が良い気がしてきました。。

@qwerty2501
Copy link
Contributor

cudaがサイズ大きいのでcudaを特別扱いし、サイズが許容できないサイズになりそうであればcoreが入ったzipとcuda関連のライブラリが入ったzipに分けるで良いような気がします。
7zにするとユーザーの使い勝手もあまりよくなさそうですし。
cuda版分けることになったらダウンロードスクリプトあったほうが良さそうですね。

@Hiroshiba
Copy link
Member Author

CUDAをダウンロード形式にすると、あと別パッケージが必要なのはDirectMLだけなので、そっちもダウンロードで良いかもとちょっと思いました・・・!

@qwerty2501
Copy link
Contributor

DirectMLについてはかなりサイズが小さそう?なので一緒にダウンロードで良いかなと思ってます

@qwerty2501
Copy link
Contributor

@Hiroshiba cudaのzip分けるか分けないか判断する参考にしたいのですが、具体的にどの程度のサイズを超えたら分けたほうが良いと考えてますか?

@Hiroshiba
Copy link
Member Author

1.3GBくらいを超えると怖い(避けたい)、1.5GB超えるとだいぶ怖い、という感覚です。

そういえば、CUDA版が必要なのはlinuxだけかなと思うのですが、linuxだとたしかaptとかyumでCUDA入れられるはずです。
同梱するよりパッケージ管理ツールでインストールしてもらったほうがユーザー的には試しやすいかもとちょっと思いました。

@qwerty2501
Copy link
Contributor

同梱させる場合でもこれまで通りのcoreとonnxruntimeのみのzipもmin版として提供させます。これはDirectML版でも同様

@qwerty2501
Copy link
Contributor

既存のものでcuda関連のもの含めてzip化してみたんですが余裕で1.5GB超えたんでやはり分けたほうが良さそうです

@Hiroshiba
Copy link
Member Author

おーーー・・・なるほどです! 検証たすかります!!

@qwerty2501
Copy link
Contributor

DirectMLについてはGPU使えるようになった?はずなのでどなたか確認お願いします

@Hiroshiba
Copy link
Member Author

DirectMLについてはGPU使えるようになった?はずなのでどなたか確認お願いします

確認してみたところ、エラーが発生したっぽいので報告します。

Exception: modelデータ読み込み中にOnnxruntimeエラーが発生しました,Failed to create session: Error calling ONNX Runtime C function and failed to convert error message to UTF-8
というエラーでした。
(python exampleを用いています。)

@Hiroshiba
Copy link
Member Author

Hiroshiba commented Aug 19, 2022

CUDA版でも試してみたところ、こんな感じのエラーが表示されました。

Exception: modelデータ読み込み中にOnnxruntimeエラーが発生しました,Failed to create session options: Error calling ONNX Runtime C function: OrtSessionOptionsAppendExecutionProvider_Cuda: Failed to load shared library

一応、同じディレクトリ内にあるdllの一覧はこちらです。

$ ls *.dll
core.dll*         onnxruntime_providers_cuda.dll*    onnxruntime_providers_tensorrt.dll*
onnxruntime.dll*  onnxruntime_providers_shared.dll*

(追記)あ!これ普通にCUDA系のdllがないからなだけかも・・・。

@qwerty2501
Copy link
Contributor

qwerty2501 commented Aug 20, 2022

Exception: modelデータ読み込み中にOnnxruntimeエラーが発生しました,Failed to create session: Error calling ONNX Runtime C function and failed to convert error message to UTF-8
というエラーでした。

エラーメッセージの取得に失敗してるようなのでまずそこを直してなぜ失敗してるかわかるようにしないといけないかもです

今わかってることを整理すると、 ここ でエラーが発生しているということはわかっています。またこの実装ですが他のort 呼び出しと違って OrtApiから呼び出しを行っていないです。他のAPIだと このように OrtApiオブジェクトから呼び出しを行っています。
しかしなぜ OrtSessionOptionsAppendExecutionProvider_DML は OrtApiオブジェクトから呼び出しを行っていないかというと、自動生成したコードでは OrtApi中にOrtSessionOptionsAppendExecutionProvider_DMLが含まれていなかったためです。(OrtApiは自動生成したコードです)

CUDA版についてはdllが足りないかもですね
ちなみにDirectML版ではdll隣に置いてあげて確認してました?

@qryxip
Copy link
Member

qryxip commented Aug 20, 2022

and failed to convert error message to UTF-8 (IntoStringError)についてはCP932案件でしょうかね...?

@qwerty2501
Copy link
Contributor

@qryxip そのあたりは ここ のCStringからStringに変換する際のエラーなので単純に無効なデータ渡されたらこのエラーが出るようです。
CP932かもしれませんが statusからResultに変換する際のGetErrorMessage で無効なデータが返されているだけかもしれません。

@qryxip
Copy link
Member

qryxip commented Aug 20, 2022

エラーメッセージをdbg!するのを用意してみました。これでメッセージが何なのかはわかるはずだと思います。

qryxip/onnxruntime-rs@b8f9aad

voicevox_core/crates/voicevox_core/Cargo.toml:

 derive-getters = "0.2.0"
 derive-new = "0.5.9"
 once_cell = "1.10.0"
-onnxruntime = { git = "https://github.com/VOICEVOX/onnxruntime-rs.git", version = "0.1.0" }
+onnxruntime = { git = "https://github.com/qryxip/onnxruntime-rs.git", rev = "b8f9aad523e412a270e3a0e53cd61c9f65e5f93d" }
 serde = { version = "1.0.143", features = ["derive"] }
 serde_json = "1.0.83"
 thiserror = "1.0.32"

@Hiroshiba
Copy link
Member Author

DirectML版が動かない件について調べたところ、対応するDirectML.dllがなかったため発生していたエラーなようでした。
python example内に対応するDirectML.dllを配置し、CDLL(str(Path("DirectML.dll").resolve(strict=True)))を追加して明示的に読み込むことで普通に実行できました!

UTF-8エラーが出る周りに関してもうちょっと調べてみました。
まず、DirectML.dllがtarget/debug/depsにない場合はRustのテストももちろん落ちるのですが、そのときのload_modelのエラーはこんな感じで、UTF-8に無関係そうに見えました。(見やすいように改行しています)

thread 'publish::tests::is_model_loaded_works::case_1' panicked at 'called 
`Result::unwrap()` on an `Err` value: LoadModel(SourceError(Failed to create session: 
Error calling ONNX Runtime C function: Exception during initialization: ))', 
crates\voicevox_core\src\publish.rs:612:57

じゃあなんでpython上でcore.dllを使う形だとエラーが出るのかですが・・・actionsやwindows環境といった要因が絡んでややこしいのと、python上で動かさない限りエラーは出ない気がするのと、もうエラーが出る原因がわかったのとで、まあ調査しなくてもいいかなという気持ちが正直なところです・・・!

@qwerty2501
Copy link
Contributor

まあ動いたんでいいんじゃないですか

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants