0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【aarch64】CTranslate2をソースビルドしてfaster-whisperをARM CPUで動かす

0
Last updated at Posted at 2026-02-15

概要

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.hlib64/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_DIRCUDNN_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 を使えます。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?