whisper.cppをWindows + GPUで試してみた

## はじめに
この記事はOhS(ポッドキャスト:とにかくヨシ！）さんの以下の記事を参考にさせていただきました。

https://zenn.dev/alt_shift_n/articles/f3c8d213ea308c

環境の違いか、そのままだとwhisper.cppをGPUありでうまくビルドできなかったので、
この記事でもだれかの助けになれば幸いです。

## 環境
OS: Windows 11 23H2 OSビルド(22631.4460)
CPU: i5 14600KF
GPU: RTX2060 super(8GB)
CMake: 3.26.0-rc2
IDE: Visual Studio Community 2022(17.10.5)

## CUDA Toolkitをインストール

[CUDA Toolkit 12.4 Update 1](https://developer.nvidia.com/cuda-12-4-1-download-archive)をダウンロードします
私は Windows > x86_64 > 11 > exe(network)をインストールしました
適当に次へを押しているとインストールできます
インストールオプションなど特に変えず、高速を選びました

![NVIDIA CUDA インストーラー画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703604/c945e1af-1b29-0bb3-8e89-69672ee46c69.png)

## whisper.cppのインストールからビルドまで

### 1. 好きな箇所にgitからクローンする

[whisper.cpp](https://github.com/ggerganov/whisper.cpp)からクローンします

```terminal
git clone https://github.com/ggerganov/whisper.cpp.git
```

### 2. ビルドする

```terminal
cd whisper.cpp
cmake -S . -B ./build -A x64 -DCMAKE_BUILD_TYPE=Release -DGGML_CUDA=ON
```

```terminal
./build/whisper.cpp.sln
```

構成をReleaseに変更し、ソリューションのビルドをします
私の環境では、そのままビルドすると、whisper.cppの4823行目で

```diff
- リテラル サフィックス '縲・' が無効です。
- リテラル演算子またはリテラル演算子テンプレート 'operator ""縲・' が見つかりません
```

と言われたので、これを回避するため、ソリューションエクスプローラーから
whisperのプロパティを開き、構成がすべての構成になっていることを確認し、
構成プロパティ > C/C++ > コマンドライン > 追加のオプションに

```
/utf-8
```

としてからビルドします

### 3. モデルをダウンロード

モデルのダウンロードには、whisper.cpp/models内の`download-ggml-model.cmd`を使います

```terminal
cd models
./download-ggml-model.cmd base.en 
```

## whisper.cppを試してみよう！

### フォルダの作成

whisper.cppを試す前に、どこでもいいのでフォルダを作り、
その中にモデル・サンプル音声・main.exe・dllを入れていきます。

今回私はDesktopにwhisper_testフォルダを作り、そこで作業していきます。

### モデルのコピー

まず、ダウンロードされた`ggml-base.en.bin`という名前のファイルが`whisper.cpp/models`以下にあると思うので、それを作ったフォルダ内にコピーします

### サンプル音源のコピー

`whisper.cpp/samples`内の`jfk.wav`も同じく作ったフォルダ内にコピーします

### main.exeとdllのコピー

`whisper.cpp/build/bin/Release`内から、`main.exe`と`whisper.dll`、
`ggml.dll`、`ggml-base.dll`、`ggml-cpu.dll`、`ggml-cuda.dll`それぞれを先ほどのフォルダにコピーします。

### 実際に実行してみよう！

作ったフォルダ(私の場合は`C:\Users\tas9n\Desktop\whisper_test`)でターミナルを開き、次のコマンドを打ってみてください。

```terminal
./main.exe -m ggml-base.en.bin -f jfk.wav
```

すこし長いですが、`whisper_init_with_params_no_state: use gpu = 1`や、`whisper_default_buffer_type: using device CUDA0 (NVIDIA GeForce RTX 2060 SUPER)`からGPUが正しく利用されているのがわかります。

<details><summary>ログ</summary>

```
whisper_init_from_file_with_params_no_state: loading model from 'ggml-base.en.bin'
whisper_init_with_params_no_state: use gpu    = 1
whisper_init_with_params_no_state: flash attn = 0
whisper_init_with_params_no_state: gpu_device = 0
whisper_init_with_params_no_state: dtw        = 0
ggml_cuda_init: GGML_CUDA_FORCE_MMQ:    no
ggml_cuda_init: GGML_CUDA_FORCE_CUBLAS: no
ggml_cuda_init: found 1 CUDA devices:
  Device 0: NVIDIA GeForce RTX 2060 SUPER, compute capability 7.5, VMM: yes
whisper_init_with_params_no_state: devices    = 2
whisper_init_with_params_no_state: backends   = 2
whisper_model_load: loading model
whisper_model_load: n_vocab       = 51864
whisper_model_load: n_audio_ctx   = 1500
whisper_model_load: n_audio_state = 512
whisper_model_load: n_audio_head  = 8
whisper_model_load: n_audio_layer = 6
whisper_model_load: n_text_ctx    = 448
whisper_model_load: n_text_state  = 512
whisper_model_load: n_text_head   = 8
whisper_model_load: n_text_layer  = 6
whisper_model_load: n_mels        = 80
whisper_model_load: ftype         = 1
whisper_model_load: qntvr         = 0
whisper_model_load: type          = 2 (base)
whisper_model_load: adding 1607 extra tokens
whisper_model_load: n_langs       = 99
whisper_default_buffer_type: using device CUDA0 (NVIDIA GeForce RTX 2060 SUPER)
whisper_model_load:    CUDA0 total size =   147.37 MB
whisper_model_load: model size    =  147.37 MB
whisper_backend_init_gpu: using CUDA0 backend
whisper_init_state: kv self size  =    6.29 MB
whisper_init_state: kv cross size =   18.87 MB
whisper_init_state: kv pad  size  =    3.15 MB
whisper_init_state: compute buffer (conv)   =   17.22 MB
whisper_init_state: compute buffer (encode) =   85.86 MB
whisper_init_state: compute buffer (cross)  =    4.65 MB
whisper_init_state: compute buffer (decode) =   97.27 MB

system_info: n_threads = 4 / 20 | AVX = 1 | AVX2 = 1 | AVX512 = 0 | FMA = 1 | NEON = 0 | ARM_FMA = 0 | F16C = 1 | FP16_VA = 0 | WASM_SIMD = 0 | SSE3 = 1 | SSSE3 = 1 | VSX = 0 | COREML = 0 | OPENVINO = 0 |

main: processing 'jfk.wav' (176000 samples, 11.0 sec), 4 threads, 1 processors, 5 beams + best of 5, lang = en, task = transcribe, timestamps = 1 ...


[00:00:00.000 --> 00:00:11.000]   And so my fellow Americans, ask not what your country can do for you, ask what you can do for your country.


whisper_print_timings:     load time =   176.15 ms
whisper_print_timings:     fallbacks =   0 p /   0 h
whisper_print_timings:      mel time =     6.44 ms
whisper_print_timings:   sample time =    33.72 ms /   131 runs (    0.26 ms per run)
whisper_print_timings:   encode time =    63.17 ms /     1 runs (   63.17 ms per run)
whisper_print_timings:   decode time =     4.96 ms /     2 runs (    2.48 ms per run)
whisper_print_timings:   batchd time =    80.06 ms /   125 runs (    0.64 ms per run)
whisper_print_timings:   prompt time =     0.00 ms /     1 runs (    0.00 ms per run)
whisper_print_timings:    total time =   374.84 ms
```

</details>

## つかってみて

今回私がwhisper.cppを使いたいと思った理由には、友人、またその他大勢の方の動画編集などの助けになればいいと考え、字幕生成ツールを作ろうとしたといった背景があります。
今回はwhisper.cppをビルドして、実際に動かすところまでをやりましたが、次回の記事では実際にGUIアプリケーションで、簡単に字幕生成を行えるソフトを作ろうと思います。