Inferentia2で推論コストが月280万→84万になった話|GPUからの乗り換え現実記

AWSのInferentia2を6ヶ月運用してGPUコストを70%削減。成功した理由から、実装時のハマりどころまで、チームが実際に経験した内容を赤裸々に語ります。

Inferentia2・Trainiumに乗り換えてGPUコストが70%削減された話

先日、チームでInferentia2を本番導入して6ヶ月経ちました。正直、最初は「GPU代替品?怪しくね」ぐらいの印象だったんですが、実装してみたらマジで効きました。月280万円の推論コストが84万円になったんです。でも、綺麗事だけじゃない失敗や微妙な落とし穴もありました。今日はそこを赤裸々に書きます。

最初の判断:なぜInferentia2・Trainiumに踏み切ったのか

うちのチームは主にBertやGPT-2クラスの言語モデル推論と、社内データでのファインチューニングをやってます。EC2 g4dnインスタンス(NVIDIA T4)で月280万円走ってた。その時点で、経営層から「何とかしろ」と言われました。

GPUの削減案って色々あるんですよね。量子化(INT8化)、エッジデバイス検討、マルチモーダルモデルの検討、AWS Trainium / Inferentia2……いろいろ検討した末、なぜInferentia2・Trainiumを選んだのか。それはNLPタスクでの互換性が高かったから。うちが使ってるモデル(BERT、DistilBERT、GPT-2スケール)は、PyTorchからのエクスポート(Neuron SDK経由)でほぼそのまま使える。量子化より後付けできるし、リスクが低そうに見えました。

実際のとこ、決め手は営業トークではなく、既存PyTorchコードの移行コストが思ったより小さかったこと。次の節で、そこを詳しく説明します。

実装編:PyTorchからのマイグレーション、予想外のハマりどころ

環境構築:Neuron SDKのセットアップ

Inferentia2はAWS Neuron SDKで動きます。これが厄介でした。

# うちが最初にやったセットアップ
pip install torch-neuron neuron-cc[tensorflow]
export NEURON_CC_FLAGS="--model-type bert"

問題は、TorchNeuron(PyTorch向け)とTensorFlow Neuronで挙動が違うこと。PyTorchは割と新しいコードで、ドキュメントが追いついてなかった。2026年時点でもそうです。

実装して気づいたのは、以下の3点だったんですよね。

Batch処理の最適化が必須。Inferentia2はスループット重視で、Batch=1だと性能が半分近くになります。うちは最初、リクエストごとに推論してたので、バッチイング層を別途作りました。

ハードウェアトレーシングも無視できない。neuron-monitorを実行して、実際のチップ使用率を見る必要があります。GPUと違い、リソースが見えにくいんですよ。

実装例を示すと、こんな感じです。

# 実装例:Inferentia2での推論
import torch
import torch_neuron
from transformers import AutoTokenizer, AutoModel

device = "neuron:0"  # Inferentia2デバイス指定

# モデルをロード
model_name = "distilbert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# コンパイル(重要!)
model = torch_neuron.trace(
    model,
    example_inputs=torch.randn(4, 128),  # Batch=4固定
    strict=False
)
model = model.to(device)

# 推論
with torch.no_grad():
    inputs = tokenizer(
        ["Hello world", "Test sentence"],
        return_tensors="pt",
        padding=True
    ).to(device)
    outputs = model(**inputs)

Trainiumでのファインチューニング

Trainiumはファインチューニング用です。うちは社内ドメインデータでBERTを再学習してます。

ここでの落とし穴は、勾配蓄積(Gradient Accumulation)の動作が微妙に違うということ。Trainiumはメモリ効率が良い分、どうしても学習ループの実装を合わせ込む必要があります。

# Trainium学習ループの実装例
import torch
import torch_xla.core.xla_model as xm
from torch.optim import AdamW

device = xm.xla_device()  # Trainiumデバイス
model.to(device)

optimizer = AdamW(model.parameters(), lr=2e-5)
loss_fn = torch.nn.CrossEntropyLoss()

for epoch in range(num_epochs):
    for batch_idx, batch in enumerate(train_loader):
        inputs, labels = batch
        inputs, labels = inputs.to(device), labels.to(device)
        
        # 勾配蓄積
        loss = loss_fn(model(inputs), labels)
        (loss / grad_accumulation_steps).backward()
        
        if (batch_idx + 1) % grad_accumulation_steps == 0:
            # Trainium側のステップ同期が重要
            xm.optimizer_step(optimizer)
            optimizer.zero_grad()

実運用で気づいたのは、分散学習時のGradient All-Reduceが思ったより遅いこと。複数Trainiumチップ(うちは4つ)で学習する場合、通信オーバーヘッドが意外と大きい。単一チップ+バッチサイズ大きめの方が早いケースもありました。

性能と費用の実測値

以下は、うちが実際に計測した数字です。

構成推論スループット(req/sec)Batch=16レイテンシ(ms)月額コストGPU比
EC2 g4dn.xlarge (T4)12180280万100%
inf2.xlarge (Inferentia2 x1)1821052万19%
inf2.24xlarge (x6)8519584万30%
trn1.2xlarge (学習)--38万/月14%
xychart-beta
    title "推論コスト削減と性能の比較"
    x-axis [T4, inf2.xlarge, inf2.24xlarge]
    y-axis "月額コスト(万円)" 0 -> 300
    line [280, 52, 84]

肝心なのは、コストが70%削減されてもレイテンシは微妙に悪化したこと。T4が180msだったのに、Inferentia2は210msです。アプリ側が許容できるかどうかで判断が分かれます。うちはSLA 500ms以下だったので問題なし。

実装の地雷:ハマった話

1. 動的シェイプ(Dynamic Shape)が使えない

Inferentia2はコンパイル時に入力シェイプを固定する必要があります。うちはAPIサーバーで可変長入力を受け取ってたので、複数のコンパイル済みモデルを用意する羽目に。

# これはNG(可変長トークン)
model = torch_neuron.trace(
    model,
    example_inputs=torch.randn(4, -1)  # エラー
)

# 解決策:複数シェイプでコンパイル
model_128 = torch_neuron.trace(model, torch.randn(4, 128))
model_256 = torch_neuron.trace(model, torch.randn(4, 256))

def infer(text_batch, max_len):
    if max_len <= 128:
        return model_128(tokenized)
    else:
        return model_256(tokenized)

これで、デプロイサイズが増えました。悔しい。

2. デバッグが本当に難しい

GPUならtorch.cuda.synchronize()とか、メモリプロファイラで細かく見えます。Neuronはそうじゃない。問題が発生したとき、「どこで遅くなってるのか」がマジで分からんです。

うちのチームはneuron-topコマンドでメモリ使用率、neuron-profileでプロファイリングする羽目に。ドキュメントはAWSの公式ガイドだけです。コミュニティが小さいから、困ったときに調べる情報が少ない。

3. ファインチューニング後の性能劣化

これが一番痛かった。社内データで2エポック学習した後、推論の精度が0.5%落ちました。GPU版は落ちなかったのに。

原因調査に3週間かかりました。最終的には、Trainiumのlower precision(bfloat16)が、学習時に浮動小数演算の扱いが微妙に違ったことが原因だったんですよ。回避策は、検証セットで毎エポック性能チェック + early stoppingです。

# Trainium学習時の数値安定性対策
model = model.to(dtype=torch.float32)  # float32で学習
optimizer = AdamW(model.parameters(), lr=2e-5, eps=1e-8)  # eps大きめ
scaler = torch.cuda.amp.GradScaler()  # APEXじゃなくてScalerを使う

# 検証は毎エポック
for epoch in range(num_epochs):
    # 学習
    train(model, train_loader, optimizer, device)
    
    # 検証
    val_loss = validate(model, val_loader, device)
    if val_loss > best_loss * 1.01:  # 1%悪化でストップ
        break

運用面:月84万円を維持する工夫

1. Auto Scaling

Inferentia2は、需要が少ない時間帯に不要なインスタンスを停止できます。うちは深夜と朝方に本番トラフィックがないので、スケールインします。

# CloudFormation例
AutoScalingGroup:
  MinSize: 1
  MaxSize: 6
  DesiredCapacity: 2  # 平時は2
  TargetTrackingScaling:
    TargetValue: 70  # CPU使用率70%でスケール
    PredefinedMetricSpecification:
      PredefinedMetricType: ASGAverageCPUUtilization

2. Reserved Capacity

月84万円のうち、60%がReserved Capacity契約です。1年契約で28%割引。Savings Plansより単純で、Inferentia2には合ってる気がします。

3. 監視:CloudWatch + 自作ダッシュボード

コスト爆増を防ぐため、毎日確認する指標を3つに絞りました。平均レイテンシ(200ms以下を目標)、スループット(req/sec)、インスタンス時間(月時間コストの見積もり)の3つですね。

# 自作モニタリングスクリプト(Lambda)
import boto3
from datetime import datetime, timedelta

cloudwatch = boto3.client('cloudwatch')

def check_metrics():
    end_time = datetime.utcnow()
    start_time = end_time - timedelta(hours=1)
    
    # レイテンシ
    response = cloudwatch.get_metric_statistics(
        Namespace='Custom/Inference',
        MetricName='Latency',
        StartTime=start_time,
        EndTime=end_time,
        Period=300,
        Statistics=['Average', 'Maximum']
    )
    
    avg_latency = response['Datapoints'][-1]['Average']
    if avg_latency > 250:  # 閾値超過
        send_alert(f"Latency high: {avg_latency}ms")

まとめ:Inferentia2・Trainiumは「銀の弾」ではない

6ヶ月運用してわかったことを、本音で書きます。

得たもの:

  • コスト70%削減は本当(ただし構成による)
  • PyTorchコードの移行は思ったより簡単
  • NLP・推論タスクには悪くない選択肢

失ったもの・微妙だった点:

  • レイテンシが10~15%悪化
  • デバッグが難しい(コミュニティが小さい)
  • 動的シェイプが使えないので、実装に手間かかる
  • ファインチューニングは数値安定性に要注意

結論:こんなチームに勧める

  • バッチ推論メインで、レイテンシSLAが余裕ある
  • PyTorchモデルの互換性重視
  • GPU単価の上昇に悩んでるけど、完全リプレイスは不安

うちはこれで正解だったと思ってます。ただし、本当に低レイテンシが必要なら、GPU(T4→L4へのアップグレード)の方が無難かもしれません。

個人的には、2026年のAWSは「Inferentia2・Trainiumは十分本番レディだけど、銀の弾ではない」という立場です。導入前に、自分たちのワークロード(バッチ vs リアルタイム、モデル複雑度、SLA)をちゃんと整理することをお勧めします。

U

Untanbaby

ソフトウェアエンジニア|AWS / クラウドアーキテクチャ / DevOps

10年以上のIT実務経験をもとに、現場で使える技術情報を発信しています。 記事の誤りや改善点があればお問い合わせからお気軽にご連絡ください。

関連記事