本番運用におけるPyTorch+CUDAサーバーでの「Unknown Error」問題とその対策

本番運用におけるPyTorch+CUDAサーバーでの「Unknown Error」問題とその対策

こんにちは!Qualitegプロダクト開発部です。

今日は、GPUをつかった商用サービスにて悩ましい、テストは全部通るけど、長時間運用をしていると急に起こる「CUDA error: unknown error」についての内容です。

これ、出会うと残念な気持ちになりますが、けっこうGPU商用サービス界隈では「あるある」なんです。

原因を真面目に探るには CUDAバージョン、PyTorchバージョンの調合具合、実際のアプリケーションコードまですべてソースまで追う必要があるのですが、多くの場合、運用でカバーします。

なぜなら仮に1つ原因をみつけて対処できたとしても、CUDAバージョンはしょっちゅうあがりますし、PyTorchもそれに追従して頻繁に更新されます。さらにやっかいなことに、1日、2日、いや1週間くらいは安定的に動作しているようにみえて、数週間後にとつぜんエラーが出るといった具合なので、修正確認の難易度が高いんです。

そこで本日は「開発環境や実験環境」ではなく「本番環境」で発生しがちなこのCUDA Unknown Error について問題の原因と実践的な対策について解説します。

問題の具体例

典型的なエラーは次のようなスタックトレースとして現れます:

RuntimeError: CUDA error: unknown error
CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1
Compile with `TORCH_USE_CUDA_DSA` to enable device-side assertions.

特に多く見られるのは、NumPy配列からPyTorchテンソルへの変換時に発生するエラーです:

img = torch.from_numpy(img.copy()).to(device, dtype=torch.float32)

なぜこの問題が発生するのか

この問題が発生する主な理由は以下のようなものがかんがえられます

1. CUDA・PyTorchのバージョン互換性の問題

CUDAとPyTorchのバージョンをアップグレードした後に、このようなエラーが突然発生するケースが多く見られます。

特にマイナーアップデートでさえ、内部実装の変更によって未知の互換性問題が引き起こされることがあります。例えば、CUDA 12.4から12.8へのアップグレード後、それに追従したPyTorchのアップグレード、また、そのために Pythonのバージョンをアップグレードしたときに付随して問題が発生することがよくあります。

2. GPUメモリの管理とリーク

PyTorchはGPUメモリを効率的に使用するためにキャッシュ機構を採用していますが、このキャッシュは完璧ではありません。

長時間の実行中に、小さなメモリリークが蓄積したり、メモリの断片化が進行したりします。

さらに、PyTorchのメモリ管理はアプリケーション層から詳細に制御することができません。
ざっくりとした解放命令やGC要求はできますが、それ以上の細かい制御はできずメモリの解放、予約領域の解放など簡単にはアプリ層からは触れず、あるいいみPyTorchまかせです。

2. CUDA非同期処理の特性

CUDAの多くの操作は非同期で行われるため、エラーが実際に発生した場所と報告される場所が異なることがあります。

エラーメッセージにも記載されている通り、実際のエラーは別のAPIコールでしれっと非同期的に報告されることがあります。

これによりデバッグがさらに困難になります。

3. 長時間実行の影響

商用サーバーアプリケーションは通常、数日から数週間(あるいはそれ以上)にわたって実行され続けます。

この間、小さな問題が徐々に蓄積し、最終的にはクリティカルなエラーとなって現れることがあります。

4. モデルの複雑性と負荷

当社サービスでも頻繁に実行される顔検出や画像認識などの複雑なモデルでは、大量のGPUリソースが必要とされ、長時間の高負荷状態がこの問題を引き起こす可能性が高まります。

実用的な対策

この問題に対処するための実践的なアプローチをいくつか紹介します

0.バージョンアップグレード前の長時間テスト

CUDAやPyTorchのバージョンをアップグレードする前に、必ず本番環境と同じ条件で長時間のテストを実施することが重要です。

特に注意すべき点は以下の通りです

  • 実際の負荷条件での検証 実際の運用時と同様の負荷をかけたテストを行います
  • 最低24時間の継続実行 メモリリークなどは時間経過とともに発生するため、短時間のテストでは発見できません
  • 繰り返しの処理 同じ処理を数千回繰り返すことで、安定性を確認します
# 最低でも24時間は同じ負荷で継続的に実行し、安定性を確認
for i in {1..10000}; do
    python your_processing_script.py --batch-size 32
    sleep 5
done
  • リソース使用量の監視 テスト中はGPUメモリやCPU使用率を継続的に監視し、徐々に増加する傾向がないか確認します
     このとき PyTorchやPythonの組み込み関数だけでなく、NVML(NVIDIA Management Library)を使用すて定期的に実行して監視するのがおすすめです。プロセス横断での使用メモリ量をより性格に取得することができます。
  • エラーログの監視 わずかな警告メッセージでも見逃さないようにログを注意深く監視します

互換性マトリックスの確認

PyTorchとCUDAのバージョン互換性を事前に確認します。PyTorch公式サイトには互換性マトリックスが公開されていますが、実際のアプリケーションでの互換性は環境によって異なることがあります。

当社ブログ「PyTorchがサポートするGPUの Compute Capability」 より

1. 運用面での対策

定期的な再起動の自動化

最も単純かつ効果的な対策は、サービスを定期的に再起動するスケジュールを設定することです。

# crontabの例: 毎日午前3時にサービスを再起動
0 3 * * * systemctl restart your_service

ヘルスチェックと自動再起動

定期的な再起動に加え、アプリケーションの状態を監視し、エラーが発生したら自動的に再起動するようにします

try:
    # メイン処理
    process_images()
except RuntimeError as e:
    if "CUDA error" in str(e):
        # ログ記録
        logging.error("CUDA error detected, restarting service")
        # プロセス再起動コード
        os.execv(sys.executable, ['python'] + sys.argv)

GPUリソースのモニタリング

NVML をつかってGPU使用率やメモリ消費を定期的に監視し、問題の予兆を検知します

import pynvml

def monitor_gpu():
    pynvml.nvmlInit()
    handle = pynvml.nvmlDeviceGetHandleByIndex(0)
    info = pynvml.nvmlDeviceGetMemoryInfo(handle)
    used_percent = info.used / info.total * 100
    
    # 使用率が90%を超えたら警告
    if used_percent > 90:
        logging.warning(f"GPU memory usage high: {used_percent:.2f}%")
        # 対策を実施 (キャッシュクリア、プロセス再起動など)

2. コード面での対策

コード面での一般的な対策も記載しておきましょう。
これは今回の根深い問題の処方箋ではありませんが、一般論としてご紹介いたします

CUDAキャッシュのクリア

定期的にPyTorchのCUDAキャッシュをクリアすることで、メモリリークの影響を減らすことができます

def clear_gpu_memory():
    torch.cuda.empty_cache()

# 一定回数の処理ごとにキャッシュクリア
for i, batch in enumerate(data_loader):
    process_batch(batch)
    if i % 100 == 0:
        clear_gpu_memory()

バッチサイズの最適化

こちらも一般論ですが、大きなバッチサイズはGPUメモリを圧迫します。より小さなバッチサイズを使用することで、メモリ問題を軽減できることがあります

# より小さなバッチサイズを設定
data_loader = DataLoader(dataset, batch_size=8, shuffle=True)

CPUフォールバックの実装

GPU処理に失敗した場合に自動的にCPUにフォールバックするロジックを実装すると、サービスの継続性が向上します

def process_with_fallback(image):
    try:
        # GPUで処理
        return process_on_gpu(image)
    except RuntimeError as e:
        if "CUDA error" in str(e):
            logging.warning("Falling back to CPU processing")
            # CPUで処理
            return process_on_cpu(image)
        else:
            raise

デバッグフラグの使用

エラーメッセージで推奨されているように、CUDA_LAUNCH_BLOCKING=1フラグを設定することで、非同期エラーの正確な位置を特定しやすくなります

CUDA_LAUNCH_BLOCKING=1 python your_script.py

3. アーキテクチャ面での対策

マイクロサービス化と水平スケーリング

モノリシックなアプリケーションを小さなマイクロサービスに分割することで、一部に問題が発生しても全体のサービスが継続できるようになります。

また、個別のサービスごとに再起動戦略を実装できます。

当社サービスも小さな単位でマイクロサービス化されており、同一の機能を提供するマイクロサービスが水平展開されています。マイクロサービスの定期的な再起動タイミングが重ならないようにスケジューリングすることでサービスの継続性を向上させることができます。

つまり複数のサーバーインスタンスを使用してロードバランシングすることで、一部のインスタンスが失敗しても、他のインスタンスがリクエストを処理できるようになります。

Kubernetes等のコンテナオーケストレーションツールを使用すると、こうした構成を効率的に管理できます。

まとめ

「CUDA error: unknown error」は、PyTorchとCUDAを使用した長時間実行サーバーでよく見られる問題です。

特にそれまでは安定していたのに、バージョンアップグレード後に突然発生することが多いため、事前の十分な検証と長時間テストが重要です。

この問題は完全に防ぐことは難しいものの、適切な運用戦略と予防策を組み合わせることで、その影響を最小限に抑えることができます。

バージョン互換性の慎重な検証、定期的な再起動の自動化、リソースモニタリング、コード最適化、適切なアーキテクチャ設計など、複数のアプローチを組み合わせて、信頼性の高いGPU対応サービスを構築することが重要です。

特に本番環境へのデプロイ前には、必ず数日間の安定性テストを行い、長時間実行時の問題を事前に発見することが、予期せぬダウンタイムを防ぐ鍵となります。

このような対策を導入することで、ディープラーニングやコンピュータビジョンのサーバーアプリケーションを、より安定して運用することができるでしょう。

また、当社ではGPU商用サービスをご検討中または、商用サービス運用中でお悩みをお持ちの事業者様へのGPUテクニカルコンサルティング・アドバイザリーのご提供も行っておりますので、お気軽にご相談くださいませ。

Read more

個人情報検出の精度を、どう正しく語るか ― Recall、信頼区間、代表性から考える評価設計

個人情報検出の精度を、どう正しく語るか ― Recall、信頼区間、代表性から考える評価設計

こんにちは。Qualiteg研究部です。 私たちは、個人情報(PII)や機密情報、要配慮個人情報を含むセンシティブな情報を検出・マスキングする技術(https://pii-fi.com)の開発に取り組んでいます。 その中で日々向き合っているのが、 「精度の数字を、どうすれば正直に、正しく語れるのか」 という問題です。 たとえば、検出器の Recall(再現率)が 0.95 だったとします。 これは高い数字に見えます。しかし、その数字はどの種類の文書で測ったものなのか。正解データはどう作ったのか。サンプル数は十分なのか。別の業務文書にも同じ数字を当てはめてよいのか。 精度の数字は、単独ではほとんど意味を持ちません。 「何を、どの条件で、どう数えたか」とセットになって、はじめて実務で使える数字になります。 本記事では、私たちが PII 検出の精度評価に取り組む中で得た、精度を誠実に語るための考え方を紹介します。アルゴリズムの中身ではなく、評価のしかたに焦点を当てます。 1. はじめに:「Recall 0.95

By Qualiteg 研究部
一文の依頼で、調査から資料作成まで。AIエージェント「Bestllam」のデモ動画を公開しました

一文の依頼で、調査から資料作成まで。AIエージェント「Bestllam」のデモ動画を公開しました

こんにちは! 本日は当社の統合AIプラットフォーム "Bestllam®" の AIエージェント機能のデモをご紹介いたします! 「指示は出せても、AIが本当に仕事を仕上げてくれるのか」 生成AIを業務に取り入れる企業が増えています。 しかし現場からは、こんな本音も聞こえてきます。 「使い方を覚えるより、自分でやったほうが早い」 「指示を細かく出し直しているうちに、結局時間がかかる」 「便利なのは分かるが、機密情報を入力していいのか不安」 AIを"個人の便利ツール"の域から、"部門の成果"へと引き上げる。 これが当社の法人向け統合AIプラットフォーム Bestllam(ベストラム) が掲げるテーマです。 今回、そのAIエージェント機能を実際の操作画面とともに紹介する動画を公開しました。 たった一文の依頼が、7枚のレポートになるまで 動画のデモはシンプルです。エージェントに、こう入力します。 「先月の売上を年代別に分析し、資料にまとめてください」 これだけです。すると、エージェントはまず自分でTODOリストを組み立て、何をどの順番で進めるかという段取りを示します

By Qualiteg ビジネス開発本部 | マーケティング部
NCCL error: unhandled cuda error が出たら ─ WSL2 + マルチGPU + vLLM で詰まった話

NCCL error: unhandled cuda error が出たら ─ WSL2 + マルチGPU + vLLM で詰まった話

こんにちは! Qualitegプロダクト開発部です! 今日は、Windows + WSL2 のマシンに RTX 4090 を2枚挿して、大規模なオープンモデルを vLLM で動かそうとしたら、NCCL の初期化で見事に詰まった話を書きます。 世の中に断片的にしか情報がなく、抜けるまでにかなり粘ったので、同じ構成で消耗している方の時間を少しでも節約できれば嬉しいです。 経緯 今回の目的は、次々と登場する最新のオープンモデル(オープンウェイトのLLM)を、手元で評価することでした。 オープンモデルは数週間単位で新しいものが出てきます。ベンチマークの数字だけでなく、自分たちのユースケースに対して実際にどう振る舞うのか——出力の質、速度、量子化したときの劣化具合、エージェント的なタスクの得手不得手——を、手を動かして確かめています 今回の環境は Windows + WSL2(Ubuntu) に RTX 4090 を2枚(各24GB)挿したマシンです。 nvidia-smi 上の CUDA Version は 12.8。 動かすのは大規模オープンモデルを

By Qualiteg プロダクト開発部
Claude Codeで「The model's tool call could not be parsed」が頻発する問題の原因分析と対策

Claude Codeで「The model's tool call could not be parsed」が頻発する問題の原因分析と対策

こんにちは!Qualitegプロダクト開発部です。 Claude Code(CLI)を使った開発中に、次のようなエラーが繰り返し表示されて作業が止まる現象に遭遇しました。 ● The model's tool call could not be parsed (retry also failed). リトライしても直らず、/clear で会話をリセットしても、しばらく作業を続けるとまた同じエラーが出るという状況です。本記事では、実際のセッションログ(jsonl)を解析して特定した原因と、その対策について共有します。 結論から書くと、これは利用者側の設定ミスやコンテキスト枯渇が原因ではなく、 Opus 4.7(1Mコンテキスト)+ extended thinking の組み合わせで発生する、モデル応答側のストリーミングバグ でした。 現象 エラーが発生した環境は以下のとおりです。 * Claude Code 2.1.148 * モデル: Opus 4.

By Qualiteg プロダクト開発部