16
13

More than 1 year has passed since last update.

雑魚のためのPyTorchでM1 MacのGPU使う環境構築

Last updated at Posted at 2022-05-19

あとで読み返したらめっちゃ間違っていたので修正しましたm(_ _)m
(2022年5月23日)

はじめに

この記事によると,PyTorch(pytorch==1.12.0)でM1 MacでGPUが使えるようになったらしい.
ということで環境構築して使ってみた記事です.
※2022年5月19日現在の内容です.

誰かが同じ轍を踏んでなければいいな,と思い書くことにしました.
環境構築をするたびに無力感を感じるので,タイトルに『雑魚のための』とつけました.

0から構築する人はこちらの手順でおkです
  1. Miniforge3-MacOSX-arm64をクリックしてminiforgeのインストーラーをダウンロード
  2. 下のコマンドでインストールから環境構築まで一気に実行
bash Miniforge3-MacOSX-arm64.sh
conda create -n pytorch python=3.8
conda activate pytorch
pip3 install --pre torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/nightly/cpu

気をつけること

このあたりに気をつけて進めていきましょう.

  1. miniforgeでpython環境を構築←超大事
  2. python3.8の環境構築する
  3. pip3でtorchとtorchvisionのNightlyを入れる←まぁ大事(というかこれができればおk)
  4. 動かすときはtorch.device("mps")を使う

やったこと

最終的に環境構築がうまくいったのはこの手順でした.

  1. anacondaを消してminiforgeをいれる
  2. python3.8の環境構築
  3. torchインストール
  4. 動かす

順番に見ていきましょう

anacondaを消してminiforgeを入れる

情弱雑魚な自分はなんの考えもなしにanacondaを入れていました.
PyTorch公式ブログにも書いてありますが,pythonのアーキテクチャがarm64じゃないと動きません.(私は当初x86運用でちゃんと動きませんでした.)
そしてanacondaで入れるとx86アーキテクチャのpythonがインストールされるようです.

To get started, just install the latest Preview (Nightly) build on your Apple silicon Mac running macOS 12.3 or later with a native version (arm64) of Python.

なんなら...M1Macはanacondaではなくminifogeをいれるべき,といたるとこでみかけます(これだから情弱は←).
いたるとこの一例

自分のpythonのアーキテクチャがなんなのかはpythonでこのコードを実行するとわかります.

import platform
print(platform.platform())

面倒ならコマンドでこうです.

python
import platform
platform.platform()

armならarm64と出ますが,x86ならx86が含まれたそれなりの文字列が出ます.

私のようにx86が含まれたそれなりの文字列が出てしまった残念な方は,まずはanacondaを消しましょう(きっとanacondaをインストールしているはずです).

この記事とか参考になります.

とりあえず,conda install anaconda-cleanしてanaconda-cleanしてフォルダ消せば大丈夫でした.

いったんここでPCごと再起動しておきましょう.

さて,続いてminiforgeのgithubにあるMiniforge3-MacOSX-arm64を落としましょう(一応ハイパーリンクにしておきます).
シェルスクリプトがダウンロードされるので,迷わす実行しましょう.(雑魚は迷わないのです.)

bash Miniforge3-MacOSX-arm64.sh

ここで,pythonのアーキテクチャを確認しておきましょう.

python
import platform
platform.platform()

arm64と出ればオッケーです!

python3.8の環境構築

miniforgeもanacondaと同じように環境を構築したりアクティベートしたりできます.

conda create -n hoge python=3.8
conda activate hoge

3.9と3.7は試してないのでわかりません.
ただし,3.10.0は失敗しました.
どこぞの雑魚ライブラリ(雑魚は私だ)ライブラリで3.10.0を勘違いして3.1を呼び出してエラーを吐いてました.

公式githubでは3.7.6か3.8.1以上が推奨されていますね.

torchインストール

これも公式に従ってインストールしましょう.
Preview(Nightly)->Mac->Pip->Python->CPUの組み合わせで出るコードを使いましょう.
スクリーンショット 2022-05-20 2.17.47.png

pip3でインストールしましょう.condaでのインストールもソースからビルドするのもうまくいきませんでした.おそらく雑魚には向いていなかったのです.
※condaに関しては,現時点でconda-forge内でtorchvisionに対応するpytorchのバージョンが1.11.0だった模様.

pip3 install --pre torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/nightly/cpu

一度ここでバージョンを確認しておきましょう.
目指すはpytorch==1.12.0です.

python
import torch
torch.__version__

'1.12.0.dev20220519'的な感じで1.12.0以上であることを示すものが出ればオッケーです.

ここでいったん打ち上げをしましょう.

動かす

ここまで大人しくついてきていれば動くはずです.
こんな感じで,torch.device()に引数としてmpsを与えてやります.
Metal Performance Shaders (MPS)だそうです.

a = torch.tensor([3])
device = torch.device("mps")
a.to(device)

ちなみに私が試したコードはこちらです.FashionMNISTを解いています.
公式のチュートリアルQuickStartのコードです.
自分では書きません雑魚だからです.

サンプルコード
import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets
from torchvision.transforms import ToTensor
import time

# Download training data from open datasets.
training_data = datasets.FashionMNIST(
    root="data",
    train=True,
    download=True,
    transform=ToTensor(),
)

# Download test data from open datasets.
test_data = datasets.FashionMNIST(
    root="data",
    train=False,
    download=True,
    transform=ToTensor(),
)


batch_size = 64

# Create data loaders.
train_dataloader = DataLoader(training_data, batch_size=batch_size)
test_dataloader = DataLoader(test_data, batch_size=batch_size)

# Get cpu or gpu device for training.
# device = "cpu"
device = "mps"
# device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")

# Define model
class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(28*28, 512),
            nn.ReLU(),
            nn.Linear(512, 512),
            nn.ReLU(),
            nn.Linear(512, 10)
        )

    def forward(self, x):
        x = self.flatten(x)
        logits = self.linear_relu_stack(x)
        return logits

model = NeuralNetwork().to(device)
print(model)

loss_fn = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)

def train(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)
    model.train()
    for batch, (X, y) in enumerate(dataloader):
        X, y = X.to(device), y.to(device)

        # Compute prediction error
        pred = model(X)
        loss = loss_fn(pred, y)

        # Backpropagation
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if batch % 100 == 0:
            loss, current = loss.item(), batch * len(X)
            # print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")

def test(dataloader, model, loss_fn):
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    model.eval()
    test_loss, correct = 0, 0
    with torch.no_grad():
        for X, y in dataloader:
            X, y = X.to(device), y.to(device)
            pred = model(X)
            test_loss += loss_fn(pred, y).item()
            correct += (pred.argmax(1) == y).type(torch.float).sum().item()
    test_loss /= num_batches
    correct /= size
    # print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")


start = time.time()
epochs = 50
for t in range(epochs):
    # print(f"Epoch {t+1}\n-------------------------------")
    train(train_dataloader, model, loss_fn, optimizer)
    test(test_dataloader, model, loss_fn)
print("Done!")
end = time.time()
print(end-start)

結論から申しますと,転送速度がボトルネックになったようでcpuのまま走らせた方が速かったです.
50エポック学習させた結果こんな感じでした.

デバイス 学習時間
cpu 133.8357961177826
mps 208.2523648738861

まぁ,MNISTですからね...

おわりに

なにはともあれ無事に環境構築できてよかったです.ありがとうPyTorch.
終わりよければ全てよし.
(というか,M1 Macのpytorchのインストール記事になってしまった.)
もっと重いモデルとデータセットで試してきちんと効能を得たいところ.
何か変な部分があればご指摘いただければと思います(何せ雑魚なので...)

16
13
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
16
13