Ryeで構築するPytorch+CUDA環境（uv追記）

# 背景
新年度になって計算用のPCを新調したこともあり、これまでルーズに構築していたPython環境を整備しようと思いました。今後の備忘録にも手順をまとめておきます。

`pipenv`, `pyenv`, `poetry`, `venv` と様々な管理手法が存在する中で、 [昨今話題のRye](https://zenn.dev/watany/articles/f69db9e33d4427) に注目しました。コアになるPythonをインストールして周辺ツールをインストールしてとやる必要がなく、 [`Rye`](https://rye-up.com/guide/) をインストールすれば良い、という点が好きです。

# 環境
## OS
* エディション	Windows 11 Pro
* バージョン	22H2
* OS ビルド	22621.1848

WSL2環境ではなく、Windows11で進めていきます。

## CUDA
* CUDA: release 11.6, V11.6.55
* cuDNN: 8.6.0

いつもの手順なので割愛させていただきます。[こちら](https://qiita.com/d83yk/items/f4e5019d3f4bbeaf36dc) の記事がわかりやすかったです。

## Rye
* rye 0.9.0
* platform: windows (x86_64)
* self-python: cpython@3.11
* symlink support: true

# Ryeのインストール
公式の [User Guide - Installation](https://rye-up.com/guide/installation/) を見ながら作業しました。

1. インストーラのダウンロード
2. インストーラの実行
3. 環境変数 `Path` の追加
    - %USERPROFILE%\.rye\shims
    - %USERPROFILE%\.rye
 
# RyeによるPythonプロジェクト操作

基本的な操作は公式の [User Guide - Basics](https://rye-up.com/guide/basics/) にまとまっています。

## プロジェクトの作成

```console
rye init newproject
```

で `newproject` というプロジェクトフォルダが作成されます。プロジェクトフォルダの初期状態は下記の通り。

```
newproject
├── .git
├── .gitignore
├── .python-version
├── README.md
├── pyproject.toml
└── src
    └── newproject
        └── __init__.py
```

`pin` コマンドを実行することで、このプロジェクトでターゲットとするPythonバージョンが `.python-version` ファイルに保存されます。

```console
rye pin <VERSION>
```

`sync` コマンドを実行することで、`pin` コマンドで指定したPythonバージョンに合わせて仮想環境が作成されます。この `sync` コマンドは、後述するライブラリの追加などを行った際に適宜実行することになります。

```console
rye sync
```

```
newproject
├── .git
├── .gitignore
├── .python-version
├── .venv          <-new!!
├── README.md
├── pyproject.toml
└── src
    └── newproject
        └── __init__.py
```

## 仮想環境へライブラリを追加

私の環境では `Pytorch 1.12.1` を追加します。公式の [Previous Pytorch Versions](https://pytorch.org/get-started/previous-versions/#linux-and-windows-7) を確認すると

```console
pip install torch==1.12.1+cu116 torchvision==0.13.1+cu116 torchaudio==0.12.1 --extra-index-url https://download.pytorch.org/whl/cu116
```

を実行すれば良いことがわかります。しかし、これは `pip` での導入方法になりますので、 `Rye` で同様の設定を行う必要があります。

`add` コマンドを実行することで、プロジェクトのライブラリ依存関係を管理するlockファイルがプロジェクトフォルダ内に作成されます。

```console
rye add "torch==1.12.1+cu116"
rye add "torchaudio==0.12.1+cu116"
rye add "torchvision==0.13.1+cu116"
```

```
newproject
├── .git
├── .gitignore
├── .python-version
├── .venv
├── README.md
├── requirements.lock     <-New!!
├── requirements-dev.lock <-New!!
├── pyproject.toml
└── src
    └── newproject
        └── __init__.py
```

上述した 'sync' コマンドは、実行時にこれらのlockファイルを参照して、必要なライブラリを仮想環境へインストールします。今回はその前にwheelを検索するソースを追加する必要があります。

```toml:pyproject.toml
[[tool.rye.sources]]
name = "torch"
url = "https://download.pytorch.org/whl/cu116"
type = "index"
```

プロジェクトフォルダ内に作成された `pyproject.toml` ファイルに上記を追記します。これにより、`sync` コマンド実行時に適切にwheelファイルがダウンロードされます。

```console
rye sync
```

あとは仮想環境の更新を待つだけです。完了後は仮想環境を起動してCUDAが有効になっていることを確認してください。

```console
.venv\Script\activate.bat
python
```

```python:(.venv)
import torch

print(torch.cuda.is_available())
```



```console
rye run 
```

で仮想環境内のPythonを直接実行することも可能です。
![2023-06-22_11h53_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131278/2fa1815d-5278-500b-2bd4-f7cd299d3212.png)

# 追記（2024/08/23）
2月にRyeがAstral管理になりましたが、そのAstralのuvがプロジェクトやPythonインタープリタ自体の管理もできるようになりました（[Astral Blog post](https://astral.sh/blog/uv-unified-python-packaging)）。

uv移行後に本記事と同様の環境構築を下記に追記します（[参考](https://docs.astral.sh/uv/reference/settings/#extra-index-url)）。

```toml:pyproject.toml
[tool.uv]
extra-index-url = ["https://download.pytorch.org/whl/cu116"]
```

# あとがき
Python本体のバージョン管理やライブラリのバージョン管理は、必要だな～と感じる頃には既存資産が大きく身動きが取りにくくなりがちです。かと言ってやろうとするとデファクト・スタンダードがたくさんあり、結局どれが良いのかと路頭に迷うことになります。個人的には、Ryeだけをインストールすれば始められるという点がシンプルでとても好ましかったです。本記事が皆様の参考になれば幸いです。

# 参考
* [Rye公式](https://rye-up.com)
* [久しぶりのPython環境をRyeで整える](https://zenn.dev/watany/articles/f69db9e33d4427)
* [Previous PyTorch Versions](https://pytorch.org/get-started/previous-versions/)
* [PyTorch-CUDA+cuDNN環境構築 on Windows 11](https://qiita.com/d83yk/items/f4e5019d3f4bbeaf36dc)
* [Basic support for changing indexes #199](https://github.com/mitsuhiko/rye/pull/199)
* [Dependency Sources](https://github.com/mitsuhiko/rye/blob/3cbfdf3363e7df7058b753c831d9b09d1a503833/docs/guide/sources.md)