0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MacでPyTorchのGPU推論行う

Last updated at Posted at 2025-12-06

はじめに

MacのApple Silicon(M1/M2/M3/M4)では、PyTorchのMPS(Metal Performance Shaders)バックエンドを使用することで、GPU推論を大幅に高速化できます。本記事では、uv環境でのセットアップから実際のベンチマーク結果まで、簡潔に解説します。

環境

  • MacBook Pro M4
  • PyTorch 2.9.1
  • Python 3.10.19(Homebrew)
  • uvパッケージマネージャー

1. 環境構築

uv仮想環境の作成

# 仮想環境を作成
uv venv

# 仮想環境を有効化
source .venv/bin/activate

PyTorchのインストール

# PyTorchとtorchvisionをインストール
uv pip install torch torchvision

2. MPSの有効化方法

PyTorchでMPSデバイスを使用するのは非常に簡単です。

import torch

# MPS利用可能性の確認
if torch.backends.mps.is_available():
    device = torch.device("mps")
    print("MPSデバイスが利用可能です")
else:
    device = torch.device("cpu")
    print("CPUを使用します")

# モデルとデータをMPSデバイスに転送
model = model.to(device)
input_data = input_data.to(device)

3. 推論速度比較

ResNet18を使った画像分類タスクで、CPUとMPSの推論速度を比較しました。

ベンチマーク条件

  • モデル: ResNet18(事前学習済み)
  • 入力: バッチサイズ32、224×224のRGB画像
  • 計測回数: 100回(ウォームアップ10回)

実装コード

import torch
import torchvision.models as models
import time

# モデル準備
model = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
model.eval()

# デバイス選択
device = torch.device("mps")  # または "cpu"
model = model.to(device)

# ダミーデータ
dummy_input = torch.randn(32, 3, 224, 224, device=device)

# 推論実行
start = time.time()
with torch.no_grad():
    output = model(dummy_input)

# MPS使用時は同期が必要
if device.type == "mps":
    torch.mps.synchronize()

elapsed = time.time() - start

結果

デバイス 平均推論時間 スループット
CPU 454.29 ms 2.20 batch/sec
MPS (GPU) 58.29 ms 17.15 batch/sec

高速化率: 7.79倍

まとめ

  • uvを使ったPyTorch環境構築は簡単で高速
  • MPSバックエンドはtorch.device("mps")で簡単に利用可能
  • M4 MacではCPUと比較して約8倍の高速化を実現
  • 推論処理が大量にある場合、MPSの活用で大幅な時間短縮が可能

サンプルコード

完全なベンチマークコードは以下で公開しています。

"""
PyTorch MPS (Metal Performance Shaders) vs CPU 推論速度比較
"""

import torch
import torchvision.models as models
import time
import numpy as np


def check_mps_availability():
    """MPS利用可能性を確認"""
    return torch.backends.mps.is_available() and torch.backends.mps.is_built()


def prepare_model_and_data(device):
    """モデルとデータを準備"""
    model = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
    model.eval()
    model = model.to(device)

    dummy_input = torch.randn(32, 3, 224, 224, device=device)
    return model, dummy_input


def benchmark_inference(model, input_data, num_iterations=100):
    """推論速度をベンチマーク"""
    inference_times = []

    # ウォームアップ
    for _ in range(10):
        with torch.no_grad():
            _ = model(input_data)

    # 計測
    for _ in range(num_iterations):
        start_time = time.time()
        with torch.no_grad():
            _ = model(input_data)

        if 'mps' in str(input_data.device):
            torch.mps.synchronize()

        end_time = time.time()
        inference_times.append(end_time - start_time)

    return np.mean(inference_times) * 1000  # ミリ秒


def main():
    # CPU
    cpu_device = torch.device("cpu")
    cpu_model, cpu_input = prepare_model_and_data(cpu_device)
    cpu_time = benchmark_inference(cpu_model, cpu_input)

    # MPS
    if check_mps_availability():
        mps_device = torch.device("mps")
        mps_model, mps_input = prepare_model_and_data(mps_device)
        mps_time = benchmark_inference(mps_model, mps_input)

        print(f"CPU: {cpu_time:.2f} ms")
        print(f"MPS: {mps_time:.2f} ms")
        print(f"高速化率: {cpu_time/mps_time:.2f}x")


if __name__ == "__main__":
    main()

参考

0
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?