Note to Self by notekunst

ただの備忘録です

古いGPU(CUDA CC=3.0)のためのPyTorchのビルド(Ubuntu 22.04 on MacBookPro 15" Late2013)

CUDA, cuDNN, pytorch のいろいろなバージョンの組み合わせを試してみました。
以下の組み合わせで、一部の機能が、一応、動くようになりました。

GPU GeForce GT 750M (Compute Capability 3.0)
Display Driver 418.113 (nvidia-smiによると470.129.06)
CUDA 10.2
cuDNN 7.6.5
pytorch 1.9.1
torchvision 0.10.1
torchaudio 0.9.1

pytorch v0.3.1 のリリースノートには、以下の説明があります。
「バイナリから CUDA capability 3.0 と 5.0 のサポートが削除されました(今のところソースからビルドすれば動作しますが、今後のサポートは削除されます)」
https://github.com/pytorch/pytorch/releases?page=3
できるだけ新しい pytorch を使いたかったので、現時点の最新版(v1.12.0)から遡りつつ順番にビルドしてみました。
v1.12.0 から v1.10.2 までは、 GPU の機能不足("__funnelshift_r"が無いなど)により、ビルドできませんでした。
v1.9.1 は、ソースコードを修正して、なんとかビルドに成功しました。
以下、ビルド作業の記録です。

pytorch v1.9.1 のビルドの手順

v1.9.1 の README.md の "From Source"にビルドの手順が記載されています。
https://github.com/pytorch/pytorch/tree/v1.9.1#from-source
これを参照して、ビルドを進めます。

ソースコードのダウンロード

適当なディレクトリを作成して、ソースコードをダウンロードします。

git clone --depth 1 --recursive https://github.com/pytorch/pytorch -b v1.9.1

ソースコードの修正

以下の3項目を修正しました。
(1) torch/utils/cpp_extension.py の修正
(2) MAGMA initialization のバグフィックス
(3) テスト用のデータの URL の修正

torch/utils/cpp_extension.py の修正

torch/utils/cpp_extension.py に '3.0' を追加する修正を行います。以下の下線部を追加しました。

    named_arches = collections.OrderedDict([
        ('Kepler+Tesla', '3.7'),
        ('Kepler', '3.0;3.5+PTX'),
...
    supported_arches = ['3.0','3.5', ...
MAGMA initialization のバグフィックス

v1.9.1 には、MAGMAの初期化に失敗するバグがあります。v1.10.0 には、このバグフィックスが取り込まれました。以下のコミットを参照して、同じようにソースコードを修正します。
https://github.com/pytorch/pytorch/commit/296d2a4399923370dccc5f3f4fc0f5fd12db4d19
このバグフィックスでは、以下の4つファイルが修正されます。
(1) aten/src/THC/CMakeLists.txt
(2) aten/src/THC/THCTensorMathMagma.cu -> .cpp
(3) aten/src/THC/THCTensorMathMagma.cuh -> .h
(4) aten/src/THC/generic/THCTensorMathMagma.cu -> .cpp
(2) (3) (4)のファイルの拡張子が変更され、(1) (2) (4)のファイル内容が修正されます。
大規模な修正ではなかったので、手作業でソースコードを修正しました。

テスト用のデータの URL の修正

torch/testing/_internal/common_utils.py に記載されている2つの url を以下のように修正します。

...
#url = "https://raw.githubusercontent.com/pytorch/test-infra/master/stats/slow-tests.json"(旧URLをコメントアウト)
 url = "https://raw.githubusercontent.com/pytorch/test-infra/generated-stats/stats/slow-tests.json"(新URLに設定)
...
#url = 'https://raw.githubusercontent.com/pytorch/test-infra/master/stats/disabled-tests.json'(旧URLをコメントアウト)
 url = 'https://raw.githubusercontent.com/pytorch/test-infra/generated-stats/stats/disabled-tests.json'(新URLに設定)

これらの url は、ビルド後のテストで参照するデータを示しています。

conda の仮想環境の作成

私は conda の仮想環境下でビルドを進めました。まず、pytorch 用の仮想環境を作成します(以下のXXXXXは、任意の仮想環境名です)。

$ conda create -n XXXXX python=3.8 setuptools=58.0.4
$ conda activate XXXXX

setuptools=58.0.4 を指定する理由は、ビルド時の以下のエラーを避けるためです。
「AttributeError: module 'distutils' has no attribute 'version'」
ネットで調べると、このエラーは、setuptools が新しい場合に発生し、setuptools のバージョンを 59.5.0 までダウングレードすればエラーが解消するようです。conda search setuptools で検索したところ、59.5.0 は見つかりませんが 58.0.4 が見つかりました。そこで、setuptools=58.0.4 を指定しました。

ビルドの準備

v1.9.1 の README.md (https://github.com/pytorch/pytorch/tree/v1.9.1#from-source) の "From Source" を参照しつつ、準備を進めます。

$ conda install astunparse numpy ninja pyyaml mkl mkl-include cmake cffi typing_extensions future six requests dataclasses   (ここで、setuptools を省略します)
$ conda install -c pytorch magma-cuda102
$ conda install typing pytest scipy parameterized hypothesis pillow
$ export CMAKE_PREFIX_PATH=${CONDA_PREFIX:-"$(dirname $(which conda))/../"}
$ export USE_CUDA=1 USE_CUDNN=1 TORCH_CUDA_ARCH_LIST="3.0" 

ここで setuptools が更新されないように気をつけます。

TORCH_CUDA_ARCH_LIST には "3.0" を設定します。

追加のツール typing, pytest, scipy, parameterized, hypothesis, pillow のインストールは、pytorch, torchvision, torchaudio のテストのためです。scipy をインストールすると、blas, intel-openmp, libgfortran-ng, mkl, numpy, numpy-base がダウングレードされてしまいます。pytorch のビルドの後にダウングレードが生じると、pytorch の再ビルドが必要になるので、ビルドの前にインストールします。

ビルド開始

ビルドには、数時間かかります。時間に余裕がある場合、"MAX_JOBS" を設定してスレッド数を少なくするといいかもしれません(MacBookPro 15" Late 2013では、最大は 8 です)。ビルド時間が更に長くなりますが、長時間の発熱によるダメージは軽減されると思います。

$ export MAX_JOBS=2  (任意)
$ python setup.py install

これで、ビルド、インストールが完了しました。

テスト

pytorch のソースコードの pytorch/test/ には、テスト用のスクリプトがあります。pytorch の以下の記事には、テスト方法の説明があります。
https://github.com/pytorch/pytorch/blob/v1.9.1/CONTRIBUTING.md#unit-testing=
"test_"で始まるファイルのそれぞれが、テスト用のスクリプトです。

以下のコマンドにより、複数のテストが順番に行われます。

$ python pytorch/test/run_test.py

以下のように1つのテストを実行することもできます。

$ python pytorch/test/test_cuda.py

run_test.py では、変数 TESTS にテストのリストが設定されています。沢山のテストが準備されています。テストの実行には、かなり時間がかかります。エラーが発生すると、そこでテストが中断します。私は、完了したテストとエラーのあるテストをコメントアウトして、続きのテストを進行しました。例えば、以下のように最初の'test_import_time'から'test_cuda'までをコメントアウトすれば、'test_jit_cuda_fuser'からテストを開始できます。

TESTS = [
#    'test_import_time',
#    'test_public_bindings',
...
#    'distributed/test_c10d_spawn_nccl',
#    'test_cuda',
    'test_jit_cuda_fuser',
...

現時点でのテスト結果は、こんな感じです

from "test_import_time" to "distributed/test_c10d_spawn_nccl" OK
"test_cuda" CUDA out of memory
"test_jit_cuda_fuser" a PTX JIT compilation failed
from "test_cuda_primary_ctx" to "distributions/test_constraints" OK
"distributions/test_distributions" ValueError (relative tolerance)
from "test_dispatch" to "test_foreach" OK
"test_indexing" CUDA out of memory
"test_jit" "__ldg" is undefined
"test_linalg" CUDA out of memory, no kernel image is available
from "test_logging" to "test_numba_integration" OK
"test_nn" CUDA out of memory, "__ldg" is undefined

テストに時間がかかるので、一部の項目しか確認できていません。
これらの結果を簡単に検討してみました。

  • "CUDA out of memory" については、仕方ないと思います(本機の GPU メモリは 2GB なので)。
  • JIT のエラーについては、要検討です。
  • "__ldg" は Capability 3.0 には無い機能なので、仕方ないと思います。"__ldg" を従来の関数を用いて定義し直せば、エラーを解消できるかもしれません。
  • "distributions/test_distributions"の計算エラーについては、要検討です。ネットで検索すると、scipy のバージョンを変えたらテスト結果が変わる、という話を見つけました。https://github.com/pytorch/pytorch/issues/60347 これが今回の件に当てはまるのか、未確認です。
  • "test_linalg" の "no kernel image is available" については、エラーメッセージで指摘された関数(torch.linalg.cond など)のサンプルコードを実行したところ、正常に動作しました。エラーの原因は linalg の関数とは別のところにあるのかもしれません。なお、linalg のサンプルコードは、pytorch のドキュメントの各関数のページにあります。https://pytorch.org/docs/1.9.1/linalg.html


未確認の多数のテストが残っていますが、それらについては、またそのうちに・・・。

とりあえず、"__ldg"、JITなどの一部の機能を用いなければ、いろいろな計算で遊べると思います。