概要
aarch64(ARM64)環境で faster-whisper を使いたい場面に遭遇しました。
faster-whisper は内部的にCTranslate2を利用していますが、残念ながらCTranslate2の公式PyPIパッケージaarch64向けはCPU-onlyの配布となっています。
つまり、aarch64環境でGPUを使うにはソースからビルドする必要があります。
この記事では、CTranslate2 v4.7.0 をaarch64+CUDA環境でソースビルドし、Pythonバインディングまでインストールする手順を解説します。
実際にビルドしてみて遭遇したハマりポイントも詳しく紹介するので、同じ環境で苦労している方の参考になれば幸いです。
前提条件
| 項目 | 要件 |
|---|---|
| CPU アーキテクチャ | aarch64(ARM64) |
| CUDA Toolkit | インストール済み(nvcc にパスが通っていること) |
| CMake | 3.18 以上 |
| GCC / G++ | インストール済み |
| Git | インストール済み |
| uv | Python パッケージインストール用 |
検証環境
| 項目 | バージョン |
|---|---|
| GPU | NVIDIA GH200 120GB |
| CUDA Toolkit | 12.4 |
| GCC | 11.4.1 |
| Python | 3.13 |
| cuDNN | 9.10.2(pip パッケージ nvidia-cudnn-cu12) |
| torch | 2.9.1(cu128) |
| torchaudio | 2.9.1(cu128) |
nvidia-smi
$ nvidia-smi
Sun Feb 15 17:12:45 2026
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.163.01 Driver Version: 550.163.01 CUDA Version: 12.4 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA GH200 120GB On | 00000009:01:00.0 Off | 0 |
| N/A 24C P0 84W / 700W | 1MiB / 97871MiB | 0% Default |
| | | Disabled |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| No running processes found |
+-----------------------------------------------------------------------------------------+
ソースコードのクローン
今回はv4.7.0にバージョンを固定してビルドします。
git clone --branch "v4.7.0" --depth 1 --recurse-submodules \
https://github.com/OpenNMT/CTranslate2.git
リリース一覧は GitHub Releases ページ で確認できます。
環境変数の準備
ビルドに必要な環境変数を設定します。
# ---- 環境に合わせて書き換えてください ----
CTRANSLATE2_SRC_DIR=/path/to/CTranslate2
CTRANSLATE2_INSTALL_DIR=/path/to/ctranslate2-cuda
PYTHON=/path/to/your/python
CUDA の確認
module システムを使う場合の注意点
NVIDIA HPC SDK が読み込まれた状態だと、コンパイラが nvc++(NVHPC)になり、nvcc のパスも HPC SDK 内を指してしまいます。CTranslate2 は GCC でのビルドが前提なので、以下のようにモジュールをリセットしてください
module purge
module load cuda/12.4
これにより、コンパイラが GCC に戻り、CUDA_HOME も正しいパスに設定されます。
CUDA_ROOT="${CUDA_HOME:-$(dirname "$(dirname "$(which nvcc)")")}"
echo "CUDA_ROOT: $CUDA_ROOT"
CUDA_ROOT 配下に include/cuda_runtime.h と lib64/libcudart.so が存在することを確認してください。
なお、libcudart.so の配置先はディストリビューションや CUDA のインストール方法によって lib64/ の場合と lib/ の場合があります。
私は、lib64だったため、lib64前提で書いています。
# 確認コマンド
find "$CUDA_ROOT" -name "cuda_runtime.h" 2>/dev/null
find "$CUDA_ROOT" -name "libcudart.so" 2>/dev/null
実行結果
CUDA_ROOT: /apps/cuda/12.4
$ find "$CUDA_ROOT" -name "cuda_runtime.h" 2>/dev/null
/apps/cuda/12.4/include/cuda_runtime.h
$ find "$CUDA_ROOT" -name "libcudart.so" 2>/dev/null
/apps/cuda/12.4/lib64/libcudart.so
もし見つからない場合は、CUDA_ROOT のパスが間違っています。which nvcc の結果から正しいパスを特定してください。
cuDNN の検出
cuDNN はオプションですが、有効にすると推論が高速になる場合があります。
pip パッケージ nvidia-cudnn-cu12 を使う場合は、以下のように検出・設定します。
CUDNN_PATH=$("${PYTHON}" -c "import nvidia.cudnn; print(nvidia.cudnn.__path__[0])" 2>/dev/null) || true
if [ -z "$CUDNN_PATH" ]; then
echo "WARNING: nvidia.cudnn パッケージが見つかりません"
echo "cuDNN なしでビルドします(-DWITH_CUDNN=OFF)"
CUDNN_CMAKE_FLAGS="-DWITH_CUDNN=OFF"
else
echo "cuDNN: $CUDNN_PATH"
CUDNN_CMAKE_FLAGS="-DWITH_CUDNN=ON -DCUDNN_INCLUDE_DIR=${CUDNN_PATH}/include -DCUDNN_LIBRARIES=${CUDNN_PATH}/lib/libcudnn.so.9"
fi
実行結果
cuDNN: /work/projects/.venv/lib/python3.13/site-packages/nvidia/cudnn
pip パッケージの cuDNN を使う場合のハマりポイント
CTranslate2 の CMakeLists.txt は cuDNN を以下のように検索しています:
find_path(CUDNN_INCLUDE_DIR NAMES cudnn.h HINTS ${CUDA_TOOLKIT_ROOT_DIR}/include)
find_library(CUDNN_LIBRARIES NAMES cudnn HINTS ${CUDA_TOOLKIT_ROOT_DIR}/lib ...)
pip パッケージの cuDNN は CUDA Toolkit とは別の場所にインストールされるため、-DCUDNN_ROOT だけでは見つけてもらえません。
CUDNN_INCLUDE_DIR と CUDNN_LIBRARIES を明示的に指定する必要があります。
pip パッケージには libcudnn.so.9 はありますが libcudnn.so(バージョンなし)は存在しません。直接 .so.9 を指定する必要があります。
CMake 構成 & ビルド
cd "$CTRANSLATE2_SRC_DIR"
mkdir -p build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DWITH_CUDA=ON \
${CUDNN_CMAKE_FLAGS} \
-DWITH_MKL=OFF \
-DWITH_DNNL=OFF \
-DOPENMP_RUNTIME=COMP \
-DCUDA_TOOLKIT_ROOT_DIR="$CUDA_ROOT" \
-DCMAKE_INSTALL_PREFIX="$CTRANSLATE2_INSTALL_DIR" \
-DCMAKE_CUDA_ARCHITECTURES=90
CMake オプションの説明
| オプション | 説明 |
|---|---|
-DCMAKE_BUILD_TYPE=Release |
最適化ありのリリースビルド |
-DWITH_CUDA=ON |
CUDAサポートを有効化 |
-DWITH_MKL=OFF |
Intel MKL を無効化 |
-DWITH_DNNL=OFF |
Intel oneDNN を無効化 |
-DOPENMP_RUNTIME=COMP |
コンパイラ付属のOpenMPを使用 |
-DCMAKE_CUDA_ARCHITECTURES=90 |
ターゲットGPUアーキテクチャ(後述) |
CMAKE_CUDA_ARCHITECTURES は自分のGPUに合わせて変更してください
本記事では GH200(Hopper / SM 9.0)を対象としているため 90 を指定しています。この値をそのまま使うと、他のGPUアーキテクチャでは動作しません。
複数アーキテクチャ向けにビルドする場合は、セミコロン区切りで指定できます(例:-DCMAKE_CUDA_ARCHITECTURES="80;86;90")。
また、CMake 3.24 以降では -DCMAKE_CUDA_ARCHITECTURES=native を指定すると、ビルドマシンに搭載されているGPUのアーキテクチャを自動検出してくれるそうです。
詳細は NVIDIA 公式ドキュメント を参照してください。
configure が通ったらビルドします。
make -j"$(nproc)"
ビルド中に大量の -Wunused-parameter などのwarningが出ますが、これらはCTranslate2本体のコードに起因するもので無視して問題ないと思います。
インストール
cmake --install .
CTRANSLATE2_INSTALL_DIRで指定したディレクトリに、ライブラリやヘッダがコピーされます。
実行結果
-- Compiler Id: GNU
-- Compiler Version: 11.4.1
-- Build spdlog: 1.10.0
-- Build type: Release
-- Compiling for multiple CPU ISA and enabling runtime dispatch
-- Using OpenMP: /usr/lib/gcc/aarch64-redhat-linux/11/libgomp.so;/usr/lib64/libpthread.a
-- Autodetected CUDA architecture(s): 8.6+PTX
-- NVCC host compiler: /bin/g++
-- NVCC compilation flags: -std=c++17;-Xcompiler=-fopenmp;-gencode;arch=compute_86,code=sm_86;-gencode;arch=compute_86,code=compute_86
-- Found cuDNN include directory: /work/projects/.venv/lib/python3.13/site-packages/nvidia/cudnn/include
-- Found cuDNN libraries: /work/projects/.venv/lib/python3.13/site-packages/nvidia/cudnn/lib/libcudnn.so.9
-- Configuring done (0.2s)
-- Generating done (0.1s)
-- Build files have been written to: /work/build/CTranslate2-4.7.0/build
Python バインディングのインストール
cd "${CTRANSLATE2_SRC_DIR}/python"
CTRANSLATE2_ROOT="$CTRANSLATE2_INSTALL_DIR" uv pip install --python "$PYTHON" .
CTRANSLATE2_ROOT環境変数を設定することで、Python バインディングがビルドしたライブラリを正しく参照できるようになります。
実行結果
Using Python 3.13.12 environment at: /work/projects/.venv
Resolved 4 packages in 1.38s
Built ctranslate2 @ file:///work/build/CTranslate2-4.7.0/python
Prepared 1 package in 2.09s
Uninstalled 1 package in 16ms
Installed 1 package in 47ms
- ctranslate2==4.7.1
+ ctranslate2==4.7.0 (from file:///work/build/CTranslate2-4.7.0/python)
ランタイムのライブラリパス設定
ビルド・インストールが完了しても、実行時に共有ライブラリが見つからないと ImportError になります。LD_LIBRARY_PATH にCTranslate2のライブラリパスを追加してください。cuDNN を pip パッケージで入れている場合は、そのパスも必要です。
export LD_LIBRARY_PATH="${CTRANSLATE2_INSTALL_DIR}/lib64:${LD_LIBRARY_PATH:-}"
SlurmなどのJobScriptなどに書いておくと良いと思います。
スクリプト
一発でインストールができるスクリプトを自分用に書いたので、一応添付しておきます。
set -euo pipefail
MONOREPO_ROOT=/work/projects
CTRANSLATE2_VERSION=4.7.0
CTRANSLATE2_SRC_DIR=/work/build/CTranslate2-${CTRANSLATE2_VERSION}-v4
CTRANSLATE2_INSTALL_DIR=/work/ctranslate2-cuda-v4
PYTHON="${MONOREPO_ROOT}/.venv/bin/python"
echo "Miyabi-G 環境セットアップ"
echo "MONOREPO_ROOT: $MONOREPO_ROOT"
echo "CT2 VERSION: $CTRANSLATE2_VERSION"
echo "Date: $(date)"
echo ""
echo "=== 前提チェック ==="
if ! command -v nvidia-smi &>/dev/null || ! nvidia-smi &>/dev/null; then
echo "FATAL: GPU が検出されません(nvidia-smi が失敗)"
echo "このスクリプトは GPU ノード上(インタラクティブジョブなど)で実行してください:"
exit 1
fi
echo "GPU: $(nvidia-smi --query-gpu=name --format=csv,noheader | head -1)"
ARCH=$(uname -m)
echo "Architecture: $ARCH"
if [ "$ARCH" != "aarch64" ]; then
echo "このスクリプトは aarch64用です(現在: $ARCH)"
exit 1
fi
if ! command -v module &>/dev/null; then
echo "FATAL: module コマンドが見つかりません"
exit 1
fi
module purge
module load cuda/12.4 || {
echo "FATAL: module load cuda/12.4 に失敗"
echo "利用可能なモジュール: $(module avail cuda 2>&1 | head -5)"
exit 1
}
echo "CUDA: $(nvcc --version 2>/dev/null | grep release || echo 'nvcc not found')"
for cmd in cmake gcc g++ git; do
if ! command -v "$cmd" &>/dev/null; then
echo "FATAL: $cmd が見つかりません"
exit 1
fi
done
echo "cmake: $(cmake --version | head -1)"
echo "gcc: $(gcc --version | head -1)"
echo ""
echo "=== uv インストール ==="
if ! command -v uv &>/dev/null; then
echo "uv が未インストール。インストールします..."
curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
fi
echo "uv: $(uv --version)"
echo ""
echo "=== uv sync --package mdx-whisper ==="
cd "$MONOREPO_ROOT"
uv sync --package mdx-whisper
echo "uv sync 完了"
echo ""
echo "=== CTranslate2 ${CTRANSLATE2_VERSION} ソースビルド ==="
echo "PyPI の aarch64 wheel は CPU-only (16.9MB) のため、CUDA 付きでビルド"
echo ""
if [ ! -d "$CTRANSLATE2_SRC_DIR" ]; then
echo "ソースをクローン中..."
mkdir -p "$(dirname "$CTRANSLATE2_SRC_DIR")"
git clone --branch "v${CTRANSLATE2_VERSION}" --depth 1 --recurse-submodules \
https://github.com/OpenNMT/CTranslate2.git "$CTRANSLATE2_SRC_DIR"
else
echo "既存ソースを使用: $CTRANSLATE2_SRC_DIR"
fi
cd "$CTRANSLATE2_SRC_DIR"
CUDA_ROOT="${CUDA_HOME:-$(dirname "$(dirname "$(which nvcc)")")}"
echo "CUDA_ROOT: $CUDA_ROOT"
CUDNN_PATH=$("${PYTHON}" -c "import nvidia.cudnn; print(nvidia.cudnn.__path__[0])" 2>/dev/null) || true
if [ -z "$CUDNN_PATH" ]; then
echo "WARNING: nvidia.cudnn パッケージが見つかりません"
echo "cuDNN なしでビルドします(-DWITH_CUDNN=OFF)"
CUDNN_CMAKE_FLAGS="-DWITH_CUDNN=OFF"
else
echo "cuDNN: $CUDNN_PATH"
CUDNN_CMAKE_FLAGS="-DWITH_CUDNN=ON -DCUDNN_INCLUDE_DIR=${CUDNN_PATH}/include -DCUDNN_LIBRARIES=${CUDNN_PATH}/lib/libcudnn.so.9"
fi
echo ""
echo "cmake 構成中..."
mkdir -p build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DWITH_CUDA=ON \
${CUDNN_CMAKE_FLAGS} \
-DWITH_MKL=OFF \
-DWITH_DNNL=OFF \
-DOPENMP_RUNTIME=COMP \
-DCUDA_TOOLKIT_ROOT_DIR="$CUDA_ROOT" \
-DCMAKE_INSTALL_PREFIX="$CTRANSLATE2_INSTALL_DIR" \
-DCMAKE_CUDA_ARCHITECTURES=90
echo ""
echo "ビルド中 ($(nproc) jobs)..."
make -j"$(nproc)"
echo ""
echo "インストール中"
cmake --install .
echo ""
echo "Python bindings インストール中"
cd "${CTRANSLATE2_SRC_DIR}/python"
CTRANSLATE2_ROOT="$CTRANSLATE2_INSTALL_DIR" \
uv pip install --python "${MONOREPO_ROOT}/.venv/bin/python" .
echo ""
echo "CTranslate2 ビルド・インストール完了"
echo ""
echo "=== 環境検証 ==="
export LD_LIBRARY_PATH="${CTRANSLATE2_INSTALL_DIR}/lib64:${LD_LIBRARY_PATH:-}"
if [ -n "${CUDNN_PATH:-}" ]; then
export LD_LIBRARY_PATH="${CUDNN_PATH}/lib:${LD_LIBRARY_PATH}"
fi
echo "--- Python ---"
echo "Python: $($PYTHON --version)"
echo "Arch: $($PYTHON -c 'import platform; print(platform.machine())')"
echo ""
echo "--- torch ---"
$PYTHON -c "
import torch
print(f'torch version: {torch.__version__}')
print(f'CUDA compiled: {torch.version.cuda}')
print(f'CUDA available: {torch.cuda.is_available()}')
assert torch.cuda.is_available(), 'FATAL: torch.cuda.is_available() が False です'
print(f'GPU count: {torch.cuda.device_count()}')
for i in range(torch.cuda.device_count()):
print(f' GPU {i}: {torch.cuda.get_device_name(i)}')
"
echo ""
echo "--- torchaudio ---"
$PYTHON -c "
import torchaudio
print(f'torchaudio version: {torchaudio.__version__}')
"
echo ""
echo "--- CTranslate2 ---"
$PYTHON -c "
import ctranslate2
print(f'ctranslate2 version: {ctranslate2.__version__}')
types = ctranslate2.get_supported_compute_types('cuda')
print(f'CUDA compute types: {types}')
assert len(types) > 0, 'FATAL: CTranslate2 が CUDA をサポートしていません'
"
echo ""
echo "--- faster-whisper ---"
$PYTHON -c "
from faster_whisper import WhisperModel
print('faster-whisper import: OK')
"
echo "--- ライブラリパス確認 ---"
echo "CTranslate2: ${CTRANSLATE2_INSTALL_DIR}/lib64"
ls -la "${CTRANSLATE2_INSTALL_DIR}/lib64/"libctranslate2* 2>/dev/null || \
ls -la "${CTRANSLATE2_INSTALL_DIR}/lib/"libctranslate2* 2>/dev/null || echo "WARNING: CT2 ライブラリが見つかりません"
pyproject.toml
[project]
name = "whisper-aarch64-gpu"
version = "0.1.0"
description = "faster-whisper on aarch64 with CUDA support"
requires-python = ">=3.12"
dependencies = [
"faster-whisper>=1.2.1",
"nvidia-cudnn-cu12",
"torch>=2.9.1",
"torchaudio>=2.9.1",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.uv.sources]
torch = { index = "pytorch-cu128" }
torchaudio = { index = "pytorch-cu128" }
[[tool.uv.index]]
name = "pytorch-cu128"
url = "https://download.pytorch.org/whl/cu128"
explicit = true
おわりに
公式が ARM 向けの GPU 対応 wheel を配布してくれれば一番楽なのですが、現状ではソースビルドが必要です。一度ビルドしてしまえば、あとは x86 環境と同じように faster-whisper を使えます。