PyTorchの利用方法


利用準備

玄界にはGPUに対応したPyTorchがインストールされており、ノードグループB, Cから利用可能です。
利用する際には以下のmoduleのloadが必要です。(ロードするモジュールのバージョンに注意してください。)
cuda/12.2.2cudnn/8.9.7nccl/2.22.3pytorch-cuda/2.3.1-12.2.2
Pythonのバージョンは3.11(python3.11コマンド)を使用する必要があります。

なおノードグループAでもCPUを用いたPyTorchの実行は可能です。
gcc/8pytorch/2.3.1をloadして利用してください。
PythonのバージョンはGPU版と同様に3.11(python3.11コマンド)を使用する必要があります。

さらに追加でPythonモジュールなどが必要となる場合はpip3.11 install --userでモジュールをインストールして利用してください。
異なるバージョンのPyTorchを使いたいときなどは、自身でのインストールや、コンテナの利用をご検討ください。

(cuda moduleをloadするとmodule availの結果にcudnnとpytorch-cudaのmoduleが表示されるようになります。同様に、gcc moduleをloadするとmodule availの結果にpytorchのmoduleが表示されるようになります。)


利用例:対象プログラム

PyTorchのサンプルとして公開されている、以下のサンプルプログラムを実行してみます。
このプログラムは冒頭のtorch.deviceの部分を書き換えることでCPU実行とGPU実行を切り替えられるため、GPU向けのものを pytorch_sample_gpu.py 、CPU向けのものをpytorch_sample_cpu.py として実行してみます。

# -*- coding: utf-8 -*-

import torch
import math


dtype = torch.float
device = torch.device("cpu")
# device = torch.device("cuda:0") # Uncomment this to run on GPU

# Create random input and output data
x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype)
y = torch.sin(x)

# Randomly initialize weights
a = torch.randn((), device=device, dtype=dtype)
b = torch.randn((), device=device, dtype=dtype)
c = torch.randn((), device=device, dtype=dtype)
d = torch.randn((), device=device, dtype=dtype)

learning_rate = 1e-6
for t in range(2000):
    # Forward pass: compute predicted y
    y_pred = a + b * x + c * x ** 2 + d * x ** 3

    # Compute and print loss
    loss = (y_pred - y).pow(2).sum().item()
    if t % 100 == 99:
        print(t, loss)

    # Backprop to compute gradients of a, b, c, d with respect to loss
    grad_y_pred = 2.0 * (y_pred - y)
    grad_a = grad_y_pred.sum()
    grad_b = (grad_y_pred * x).sum()
    grad_c = (grad_y_pred * x ** 2).sum()
    grad_d = (grad_y_pred * x ** 3).sum()

    # Update weights using gradient descent
    a -= learning_rate * grad_a
    b -= learning_rate * grad_b
    c -= learning_rate * grad_c
    d -= learning_rate * grad_d


print(f'Result: y = {a.item()} + {b.item()} x + {c.item()} x^2 + {d.item()} x^3')

GPUによる実行

ノードグループBでバッチジョブ実行する例を示します。

以下のジョブスクリプトを用いて実行します。

$ cat job_pytorch_gpu.sh
#!/bin/bash
#PJM -L rscgrp=b-batch
#PJM -L gpu=1
#PJM -L elapse=10:00
#PJM -j
#PJM -S

module load cuda/12.2.2 cudnn/8.9.7 nccl/2.22.3 pytorch-cuda/2.3.1-12.2.2
python3.11 ./pytorch_sample_gpu.py

CPUによる実行

PyTorchはGPUを使って実行することが多いと思いますが、
ノードグループAでCPUを使ってバッチジョブ実行する例も示しておきます。

以下のジョブスクリプトを用意して実行します。

$ cat job_pytorch_cpu.sh
#!/bin/bash
#PJM -L rscgrp=a-batch
#PJM -L vnode-core=10
#PJM -L elapse=10:00
#PJM -j
#PJM -S

module load gcc/8 pytorch/2.3.1
python3.11 ./pytorch_sample_cpu.py


実行結果

実行結果の例を以下に示します。
forループ内のprint文で途中経過が出力され、最後のprint文で結果が出力されています。
乱数を用いて入力データを生成しているため、実行の度に値は大きく変動します。

$ cat cat job_pytorch_gpu.sh.82610.out
99 3770.3193359375
199 2534.77490234375
299 1706.46923828125
399 1150.7528076171875
499 777.6245727539062
599 526.8876953125
699 358.253173828125
799 244.737548828125
899 168.25572204589844
999 116.67759704589844
1099 81.86070251464844
1199 58.3349609375
1299 42.4226188659668
1399 31.648521423339844
1499 24.345962524414062
1599 19.39096450805664
1699 16.025184631347656
1799 13.736391067504883
1899 12.178205490112305
1999 11.11623764038086
Result: y = -0.03617167845368385 + 0.8240451812744141 x + 0.006240217015147209 x^2 + -0.0886797159910202 x^3