# DL

## CUDA 环境配置

说明：高版本的显卡驱动兼容各个低版本的 CUDA 与 CUDNN，但 CUDA 与 CUDNN 之间存在的对应关系。CUDA 的各个版本之间一般不存在兼容性。而CUDNN实际上是一堆头文件和库文件的集合，直接放入CUDA的头文件和库文件中即可。安装顺序为：先安装最新版本的显卡驱动，再安装CUDA，再查询相匹配版本的CUDNN，并将文件复制进CUDA中即可。

### (硬件)显卡支持

显卡与CUDA版本的支持对应情况: 参考[博客](https://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/)

### (系统软件)驱动

安装驱动的方式有几种：

* ubuntu下使用命令安装：

  ```bash
  # apt search nvidia-driver
  apt install nvidia-driver-515
  ```

  此方法的好处是不需要关闭其他可能引起冲突的系统驱动，坏处是apt维护的nvidia-driver可能不是最新的不能满足需求
* 去[官方nvidia驱动下载页面](https://www.nvidia.com/download/index.aspx)下载安装脚本进行安装
* 系统级别安装CUDA时，可以将驱动也一并勾选进行安装

### (依赖软件) gcc, g++

安装 CUDA 时需要执行安装脚本，可能会涉及到 gcc/g++ 不存在或不兼容的情况，安装多个版本的 gcc/g++(ubuntu): 参考[博客](https://linuxconfig.org/how-to-switch-between-multiple-gcc-and-g-compiler-versions-on-ubuntu-20-04-lts-focal-fossa)

### TensorRT

相关下载及文档链接如下：

* CUDA Driver: <https://developer.nvidia.com/download/indec.aspx>
* CUDA版本与驱动的支持关系: <https://developer.nvidia.com/cuda/cuda-toolkit-release-notes/index.html>
* CUDA:
  * 下载及文档：<https://developer.nvidia.com/cuda-toolkit-archive>
* cuDNN:
  * 下载：<https://developer.nvidia.com/rdp/cudnn-archive>
* TensorRT:
  * 下载：<https://developer.nvidia.com/nvidia-tensorrt-download>
  * 文档：<https://docs.nvidia.com/deeplearning/tensorrt/archives/index.html>

TensorRT 依赖于 CUDA 与 cuDNN, 且特定版本的 TensorRT 依赖于特定版本的 CUDA 与 cuDNN，下面是几个版本的例子：

TensorRT 8.2 GA + cuDNN 8.2.4 + CUDA 11.4

* TensorRT 8.2 GA Update 4 for Linux x86\_64 and CUDA 11.0, 11.1, 11.2, 11.3, 11.4 and 11.5 TAR Package: TensorRT-8.2.5.1.Linux.x86\_64-gnu.cuda-11.4.cudnn8.2.tar.gz
* cuDNN v8.2.4 (September 2nd, 2021), for CUDA 11.4, for Linux (x86): cudnn-11.4-linux-x64-v8.2.4.15.tgz

TensorRT 8.2 GA + cuDNN 8.2.4 + CUDA 10.2

* TensorRT 8.2 GA Update 4 for Linux x86\_64 and CUDA 10.2 TAR Package:TensorRT-8.2.5.1.Linux.x86\_64-gnu.cuda-10.2.cudnn8.2.tar.gz
* cuDNN v8.2.4 (September 2nd, 2021), for CUDA 10.2, for Linux (x86): cudnn-10.2-linux-x64-v8.2.4.15.tgz

TensorRT 7.2.3 + cuDNN 8.1.1 + CUDA 11.1

* TensorRT 7.2.3 for Ubuntu 18.04 and CUDA 11.1, 11.2 TAR package: TensorRT-7.2.3.4.Ubuntu-18.04.x86\_64-gnu.cuda-11.1.cudnn8.1.tar.gz
* cuDNN v8.1.1 (Feburary 26th, 2021), for CUDA 11.0, 11.1, 11.2, for Linux Ubuntu(x86\_64): cudnn-11.2-linux-x64-v8.1.1.33.tgz

TensorRT 7.2.3 + cuDNN 8.1.1 + CUDA 10.2

* TensorRT 7.2.3 for Ubuntu 18.04 and CUDA 10.2 TAR package: TensorRT-7.2.3.4.Ubuntu-18.04.x86\_64-gnu.cuda-10.2.cudnn8.1.tar.gz
* cuDNN v8.1.1 (Feburary 26th, 2021), for CUDA 10.2, for Linux Ubuntu(x86\_64): cudnn-10.2-linux-x64-v8.1.1.33.tgz

CUDA Toolkit 10.2.89 (Nov 2019):

* cuda\_10.2.89\_440.33.01\_linux.run
* patch 1 (Aug 26, 2020): cuda\_10.2.1\_linux.run
* patch 2 (Nov 17, 2020): cuda\_10.2.2\_linux.run CUDA Toolkit 11.4.4 (Feburary 2022): cuda\_11.4.4\_470.82.01\_linux.run CUDA Toolkit 11.1.1 (October 2020): cuda\_11.1.1\_455.32.00\_linux.run

版本选择的方法【后续仍需补充】：

从下载后的 TensorRT 的安装包文件名可以看出其依赖的 CUDA 与 cuDNN 版本 从下载后的 cuDNN 的安装包文件名可以看出其依赖的 CUDA 版本 从下载后的 CUDA 的安装包文件名可以看出与其相适配的显卡驱动版本号（如果机器本身的显卡驱动足够高，安装时可以选择不安装显卡驱动）

### 多版本并存安装指南

参考资料

* [博客](https://towardsdatascience.com/installing-multiple-cuda-cudnn-versions-in-ubuntu-fcb6aa5194e2)
* 李沐[B站课程](https://www.bilibili.com/video/BV1LT411F77M) 主要有两种方式(除去docker的方式)：
  * 系统级别安装nvidia驱动+系统级手动安装所需要的版本的cuda 备注：此方法得到的cuda是完整的
  * 系统级别安装nvidia驱动+conda安装cudatoolkit 备注：此方法得到的cuda是不完整的

本节内容仅作宏观指导, 具体细节以官方文档为准

第一步：安装版本足够高的显卡驱动，驱动决定的支持最高的 CUDA 版本，且驱动在宿主机上只能是唯一的版本

CUDA、cuDNN、TensorRT 都可以多版本并存安装，其中 CUDA 需要执行安装脚本、而 cuDNN 和 TensorRT 只需要将下载的安装文件解压并设置好环境变量即可。

下面以这个版本为例介绍安装方法：

TensorRT 7.2.3 + cuDNN 8.1.1 + CUDA 10.2

* TensorRT 7.2.3 for Ubuntu 18.04 and CUDA 10.2 TAR package: TensorRT-7.2.3.4.Ubuntu-18.04.x86\_64-gnu.cuda-10.2.cudnn8.1.tar.gz
* cuDNN v8.1.1 (Feburary 26th, 2021), for CUDA 10.2, for Linux Ubuntu(x86\_64): cudnn-10.2-linux-x64-v8.1.1.33.tgz
* CUDA Toolkit 10.2.89 (Nov 2019):
  * cuda\_10.2.89\_440.33.01\_linux.run
  * patch 1 (Aug 26, 2020): cuda\_10.2.1\_linux.run
  * patch 2 (Nov 17, 2020): cuda\_10.2.2\_linux.run

即假设目录 `/home/username/software` 下下载好了如下文件

```
cuda_10.2.89_440.33.01_linux.run
cuda_10.2.1_linux.run
cuda_10.2.2_linux.run
cudnn-10.2-linux-x64-v8.1.1.33.tgz
TensorRT-7.2.3.4.Ubuntu-18.04.x86_64-gnu.cuda-10.2.cudnn8.1.tar.gz
```

**CUDA 安装** 参考[博客](https://blog.csdn.net/qq757056521/article/details/109267381)

```bash
# 在希望不修改/usr/local/cuda的软连接时
./cuda_10.2.89_440.33.01_linux.run --librarypath=/usr/local/cuda-10.2
./cuda_10.2.1_linux.run  # 安装 patch1
./cuda_10.2.2_linux.run  # 安装 patch2
# 安装完后可以将上面 3 个安装脚本文件全部删除
```

以上命令会将 CUDA 10.2 安装在 `/usr/local/cuda-10.2` 目录下

需要修改的环境变量有：

```bash
export PATH=/usr/local/cuda-10.2/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-10.2/lib64:$LD_LIBRARY_PATH
export CPATH=/usr/local/cuda-10.2/include:$CPATH
```

**cuDNN 安装**

参考 [stackoverflow](https://stackoverflow.com/questions/40736999/installing-cudnn-for-general-usage-without-root-access)

```bash
tar -zxvf cudnn-10.2-linux-x64-v8.1.1.33.tgz
# 官网以及许多教程会推荐将解压后的头文件与库文件直接拷贝至cuda头文件与库文件中, 这里使用分离的办法
mv cuda cudnn-10.2-linux-x64-v8.1.1.33
rm -rf cudnn-10.2-linux-x64-v8.1.1.33.tgz  # 注意不能删除解压后的文件
```

需要修改的环境变量有：

```bash
export LD_LIBRARY_PATH=/home/username/software/cudnn-10.2-linux-x64-v8.1.1.33/lib:$LD_LIBRARY_PATH
export CPATH=/home/username/software/cudnn-10.2-linux-x64-v8.1.1.33/include:$CPATH
```

**TensorRT 安装**

```bash
tar -zxvf TensorRT-7.2.3.4.Ubuntu-18.04.x86_64-gnu.cuda-10.2.cudnn8.1.tar.gz
rm -rf TensorRT-7.2.3.4.Ubuntu-18.04.x86_64-gnu.cuda-10.2.cudnn8.1.tar.gz  # 注意不能删除解压后的文件
# 可选: 安装python相关的包
cd TensorRT--7.2.3.4.Ubuntu-18.04.x86_64-gnu.cuda-10.2/python
python3 -m pip install tensorrt-*-cp3x-none-linux_x86_64.whl
```

需要修改的环境变量有：

```bash
export PATH=/home/username/software/TensorRT-7.2.3.4.Ubuntu-18.04.x86_64-gnu.cuda-10.2.cudnn8.1/bin:$PATH
export LD_LIBRARY_PATH=/home/username/software/TensorRT-7.2.3.4.Ubuntu-18.04.x86_64-gnu.cuda-10.2.cudnn8.1/lib:$LD_LIBRARY_PATH
export CPATH=/home/username/software/TensorRT-7.2.3.4.Ubuntu-18.04.x86_64-gnu.cuda-10.2.cudnn8.1/include:$CPATH
```

### (FAQ) CUDA 的多种安装方式

CUDA 的安装方式在网上各种资料里大略有如下几种，但一般来说只推荐上一节的那种方式，这里对这几种方式做一个说明：

* Nvidia 官网安装：
  * 离线安装脚本：例如上面介绍的 `cuda_10.2.89_440.33.01_linux.run`，这种安装包含了整个 CUDA 的工具包，最重要的是 nvcc 编译器、头文件、库文件，最全面
  * deb 包：这种安装也是全面的安装，缺点是它会把头文件、库文件、nvcc 分散在系统文件的各处，不方便删除
* 使用conda安装cuda-toolkit: 阉割版的cuda，且必须激活环境，总的来说不推荐

### (FAQ) cuda driver version与runtime version

```
nvidia-smi  # CUDA Drive Version
nvcc -V  # CUDA Runtime Version
```

CUDA 提供了两套 API，一套是 CUDA Driver API，另一套是 CUDA Runtime API，其中 Driver API 更为底层。

```
import torch
torch.version.cuda()  # Runtime version
```

一般而言，只需要关注 Runtime API 即可，例如在 Linux 系统中的 `~/.bashrc` 中添加这几行（添加到 PATH 与 LD\_LIBRARY\_PATH 尤为重要）指的是 Runtime API 相关的路径。

```
export CUDA_HOME=/usr/local/cuda-10.0
export PATH=$CUDA_HOME/bin:$PATH
export LD_LIBRARY_PATH=$CUDA_HOME/lib:$CUDA_HOME/lib64:$LD_LIBRARY_PATH
```

### (FAQ) Pytorch 相关

如果只希望运行Pytorch代码，可以只安装驱动，其余的CUDA、CUDNN等包含在`pip install pytorch`中[pytorch问答](https://discuss.pytorch.org/t/how-to-check-if-torch-uses-cudnn/21933)。具体来说，在官方预编译好[pytorch whl](https://download.pytorch.org/whl/torch/)包中，例如：`torch-1.11.0+cu115-cp38-cp38-linux_x86_64.whl`，将其解压后，可以发现这些文件的存在：

```
./torch/lib/libcudnn.so.8
./torch/lib/libcudnn_adv_infer.so.8
./torch/lib/libcudnn_adv_train.so.8
./torch/lib/libcudnn_cnn_infer.so.8
./torch/lib/libcudnn_cnn_train.so.8
./torch/lib/libcudnn_ops_infer.so.8
./torch/lib/libcudnn_ops_train.so.8
```

备注：pytorch中带着的cuda以及cudnn头文件及库文件并不是完整的cuda与cudnn库文件。并且即使系统级别安装的是别的版本的cuda与cudnn，使用pip的方式安装时，pytorch在运行时也会将其忽略【设置LD\_LIBRARY\_PATH会不会影响到？】。

由于pytorch自带(使用pip安装)了一个阉割版的CUDA(可能pytorch为了用户体验,只要求安装驱动其他都自带), 而某些其他的包需要独立安装一个完整的CUDA, 这时候会引发一些冲突,具体解释可以参考[参考资料](https://huggingface.co/docs/transformers/v4.24.0/en/main_classes/trainer#trainer-integrations)

新版本的 pytorch 安装时，有一些新的变化，例如安装包变小了，CUDA和CUDNN的依赖会去下载别的nvidia的包，参见[issue](https://github.com/pytorch/pytorch/issues/96595)

pytorch 预编译包有两个地方可以下载

* [PyPi](https://pypi.org/project/torch/): 对于一个torch版本而言, 对于一个系统类型(例如:windows/linux), 一个python版本(例如:python3.6/python3.7/python3.8), 只能提供一个whl安装包, 因此只能放一个CUDA版本的预编译包
* [pytorch whl](https://download.pytorch.org/whl/torch/)：对于一个torch版本而言, Pytorch 预编译了不同 CUDA 版本的预编译包

注意: 不是所有的 CUDA 版本都有预编译包, 例如 CUDA 11.4 版本就没有预编译包

以下是在Linux环境下不同python、pytorch、cuda版本下对推理过程的测试，比较结果的差异【待测试】

* pytorch1.10.2+cuda10.2+python3.7: 一致
* pytorch1.10.2+cuda10.2+python3.8
* pytorch1.10.2+cuda10.2+python3.9
* pytorch1.12.1+cuda10.2+python3.7: 一致
* pytorch1.12.1+cuda10.2+python3.8
* pytorch1.12.1+cuda10.2+python3.9
* pytorch1.12.1+cuda11.3+python3.7: 一致
* pytorch1.12.1+cuda11.3+python3.8
* pytorch1.12.1+cuda11.3+python3.9

测试方法如下：使用ubuntu镜像预编译好3种python作为3个基础镜像, 之后使用这三个镜像分别安装pytorch whl文件, 最后在huggingface上模型结果是否有差异.

### (FAQ) 怎么知道版本号

来源: ColossalAI `colossalai check -i`

```python
# 系统的CUDA版本
from torch.utils.cpp_extension import CUDA_HOME
output = subprocess.check_output([CUDA_HOME + "/bin/nvcc", "-V"], universal_newlines=True)

# torch的版本
import torch
print(torch.__version__)

# torch内部C++算子所使用的CUDA版本
print(torch.version.cuda)
```

### (FAQ) 相关的环境变量解释

* `PATH`: 可执行文件搜索目录
* `CPATH`: 头文件搜索目录
* `CUDA_HOME`: 这个某些情况下似乎会用到, 不确定是否必须
* `LD_LIBRARY_PATH`, `RPATH`, `RUNPATH`, `DT_RPATH`, `DT_RUNPATH`: 动态链接库搜索目录

[资料1](https://medium.com/obscure-system/rpath-vs-runpath-883029b17c45) [资料2](https://man7.org/training/download/shlib_dynlinker_slides.pdf) [pytorch issue](https://github.com/pytorch/pytorch/issues/96595)

### (FAQ) Nvidia 显卡架构, 型号, CUDA 时间线

参考资料

* [架构](https://en.wikipedia.org/wiki/Category:Nvidia_microarchitectures)
* [CUDA](https://developer.nvidia.com/cuda-toolkit-archive)
* [cuDNN](https://developer.nvidia.com/rdp/cudnn-archive)
* [TensorRT](https://developer.nvidia.com/nvidia-tensorrt-download)

显卡:

* 2006: Tesla
* 2010: Fermi
* 2012: Kepler
* 2014: Maxwell
* 2016: Pascal
* 2017: Volta, Tesla V100
* 2018: Turing, GeForce16 系列, RTX20 系列
* 2020: Ampere, A100, RTX3060
* 2022: Hopper, H100

CUDA:

* 2016.9: CUDA 8.0
* 2017.9: CUDA 9.0
* 2017.10: CUDA 9.1
* 2018.5: CUDA 9.2
* 2018.9: CUDA 10.0
* 2019.2: CUDA 10.1
* 2019.10: CUDA 10.2
* 2020.1: CUDA 11.0.1
* 2020.9: CUDA 11.1.0
* 2020.12: CUDA 11.2.0
* 2021.4: CUDA 11.3.0
* 2021.6: CUDA 11.4.0
* 2021.10: CUDA 11.5.0
* 2022.1: CUDA 11.6.0
* 2022.5: CUDA 11.7.0
* 2022.10: CUDA 11.8.0
* 2022.12: CUDA 12.0.0
* 2023.2: CUDA 12.1.0

cuDNN:

* 2017.4: cuDNN 6.0 (CUDA 7.5, 8.0)
* 2017.10: cuDNN 7.0.1 (CUDA 8.0, 9.0)
* 2018.3: cuDNN 7.1.2 (CUDA 9.0, 9.1, 9.2)
* 2018.8: cuDNN 7.2.1 (CUDA 9.2)
* 2018.9: cuDNN 7.3.0 (CUDA 9.0, 9.2, 10.0)
* 2018.10: cuDNN 7.4.1 (CUDA 9.0, 9.2, 10.0)
* 2019.2: cuDNN 7.5.0 (CUDA 9.2, 10.0, 10.1)
* 2019.5: cuDNN 7.6.0 (CUDA 9.2, 10.0, 10.1, 10.2)
* 2020.7: cuDNN 8.0.2 (CUDA 10.1, 10.2, 11.0)
* 2021.1: cuDNN 8.1.0 (CUDA 10.2, 11.0, 11.1, 11.2)
* 2021.4: cuDNN 8.2.0 (CUDA 10.2, 11.x, 11.4)
* 2021.10: cuDNN 8.3.0 (CUDA 10.2, 11.5)
* 2022.4: cuDNN 8.4.0 (CUDA 10.2, 11.x)
* 2022.8: cuDNN 8.5.0 (CUDA 10.2, 11.x)
* 2022.10: cuDNN 8.6.0 (CUDA 10.2, 11.x)
* 2022.11: cuDNN 8.7.0 (CUDA 10.2, 11.x)
* 2023.2: cuDNN 8.8.0 (CUDA 11.x, 12.0)
* 2023.4: cuDNN 8.9.0 (CUDA 11.x, 12.x)

TensorRT(不确定时间线在哪找)

### GPU利用率/带宽 benchmark

比较可信的工具是

* nvidia-smi: 对 nvidia 的 [NVML](https://developer.nvidia.com/nvidia-management-library-nvml) 的封装工具, 因此如果需要比较精确地把握, 直接研究 NVML 即可, nvidia-smi 本身也有许多高级用法, 参考这个 [掘金系列博客](https://juejin.cn/post/7118926640733749278)
* cuda-sample: <https://github.com/NVIDIA/cuda-samples>, 早期版本 cuda-sample 是在 CUDA toolkit 安装时附带的

其他小工具

* [nvtop](https://github.com/Syllo/nvtop)
* [gpustat](https://github.com/wookayin/gpustat)

#### 带宽

CPU <-> GPU: cuda-sample/bandwidthTest

GPU 内存带宽: cuda-sample/bandwidthTest

P2P带宽(两块GPU之间拷贝): cuda-sample/p2pBandwidthLatencyTest

## WSL2

前置条件：最好是 Windows 11

安装步骤：

* 按微软 [官方文档](https://docs.microsoft.com/en-us/windows/wsl/install) 安装 WSL2
* 在微软商店中安装 Ubuntu 20.04 以及 Windows Terminal (Windows 10) 已自带

后置事项：

* Windows 上安装 VSCode 并安装 Remote-WSL 插件
* 更换 apt 源：[清华源官网](https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/)
* 文件目录：
  * Windows 系统查看 WSL2 文件：在资源浏览器目录中输入：`\\wsl$`，或者类似这种目录 `C:\Users\{Username}\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu20.04LTS_79rhkp1fndgsc\LocalState` (不推荐)
  * WSL2 命令行（Windows Terminal）中查看 Windows 文件目录：`/mnt/c` 表示 C 盘目录
  * 在 WSL2 命令行中切换至相应目录执行 `code .` 即可打开 VSCode，并且打开后 VSCode 的集成终端本身也会是 WSL2 命令行
* GPU（不确定）：在 Windows 11 本机将 Nvidia 显卡驱动升级至 510 以上版本，那么不做特殊设置，WSL2 中也能访问显卡，在 WSL2 命令行中可以查验：`lspci | grep -i nvidia`
* Docker：可以参考 Docker 官方文档将 Docker Desktop 在 Windows 本机安装，此时 WSL2 与 Windows 本机均能使用 Docker。也可以在 WSL2 Terminal 中使用命令安装 Docker，这样 Docker 只能在 WSL2 命令行中访问
* 网络：一般情况下，无需做特殊设置，WSL2 的网络与 Windows 本机的网络一般是互通的。如果使用 VPN 或代理时，可能需要进行特殊设置（不确定）。

磁盘清理：

[参考资料1](https://stephenreescarter.net/how-to-shrink-a-wsl2-virtual-disk/) [参考资料2](https://stackoverflow.com/questions/64068185/docker-image-taking-up-space-after-deletion) 使用 Windows PowerShell 输入

```
diskpart
```

在弹出的命令行中输入

```powershell
# 清理WSL2
select vdisk file="C:\Users\xyz\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu20.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx"
compact vdisk
# 清理Docker Desktop
select vdisk file="C:\Users\xyz\AppData\Local\Docker\wsl\data\ext4.vhdx"
compact vdisk
select vdisk file="C:\Users\xyz\AppData\Local\Docker\wsl\distro\ext4.vhdx"
compact vdisk
```

### 远程访问WSL

在WSL2的terminal中

```bash
sudo apt remove openssh-server
sudo apt install openssh-server  # 选择1
sudo vim /etc/ssg/sshd_config
# 配置以下三项
# Port 2222
# PermitRootLogin yes
# PasswordAuthentication yes
sudo service ssh --full-restart
ifconfig  # 查看wsl2的ipv4, 以下用<wsl2_ip>代替
```

在WSL2的Windows宿主机打开powershell以管理员权限设置端口转发

```powershell
netsh interface portproxy set v4tov4 listenport=3333 listenaddress=0.0.0.0 connectport=2222 connectaddress=<wsl2_ip>
ipconfig  # 查看Windows本机ipv4, 以下用<windows_ip>代替
```

在WSL2的Windows宿主机设置防火墙规则:

控制面板->防火墙->入站规则->新建规则

* 端口
* TCP, 特定本地端口, 3333
* 允许连接
* 全选上
* 名称任意

至此, 从局域网中另一台机器打开终端即可远程连接WSL2

```
ssh <wsl2_user_name>@<windows_ip> -p 3333
```

## 源

### pip 源

参考：<https://mirrors.tuna.tsinghua.edu.cn/help/pypi/>

```
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
```

### anaconda 源

参考：<https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/>

windows 机器先执行

```
conda config --set show_channel_urls yes
```

在\~/.condarc中写入

```
channels:
  - defaults
show_channel_urls: true
default_channels:
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
custom_channels:
  conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  pytorch-lts: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
```

### apt 源

参考：<https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/>

```
sudo sed -i "s@http://.*archive.ubuntu.com@https://mirrors.tuna.tsinghua.edu.cn@g" /etc/apt/sources.list
sudo sed -i "s@http://.*security.ubuntu.com@https://mirrors.tuna.tsinghua.edu.cn@g" /etc/apt/sources.list
```

### 时区

```
export TIME_ZONE=Asia/Shanghai
apt install -y apt-utils tzdata
ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && echo $TIME_ZONE > /etc/timezone
dpkg-reconfigure -f noninteractive tzdata
```

Dockerfile中的写法

```dockerfile
ARG DEBIAN_FRONTEND="noninteractive"
ENV TIME_ZONE Asia/Shanghai
RUN apt install -y apt-utils tzdata && \
    ln -snf /usr/share/zoneinfo/$TIME_ZONE /etc/localtime && \
    echo $TIME_ZONE > /etc/timezone && \
    dpkg-reconfigure -f noninteractive tzdata
```

### virtualenvwrapper

安装

```
pip install pbr
pip install virtualenv virtualenvwrapper
```

配置

```
# 仅作示例
# ~/.bashrc
export WORKON_HOME=$HOME/.virtualenvs
export VIRTUALENVWRAPPER_PYTHON=/opt/conda/bin/python
export VIRTUALENVWRAPPER_VIRTUALENV=/opt/conda/bin/virtualenv
source /opt/conda/bin/virtualenvwrapper.sh
```

使用

```
mkvirtualenv env-name  # 创建
rmvirtualenv env-name  # 移除
workon env-name        # 激活环境
deactivate             # 退出环境
```

备注：

* 实际上，`workon`, `mkvirtualenv` 等命令是 virtualenvwrapper.sh 这个脚本里的函数，因此使用 `whereis workon` 会找不到位置。
* 假设环境名为 `test`，则虚拟环境的 `bin` 目录为 `$WORKON_HOME/test/bin`，此目录底下包含如下可执行命令：

  ```
  python  # 一般是软链接，链接到 mkvirtualenv 时的 python 路径
  pip  # 是 pip 包的一个 entrypoint，实际上是一个文本文件（有可执行权限），注意观察第一行以#!开头，记录了执行时的python路径
  activate  # 是一个shell脚本, 注意其中有一行：VIRTUAL_ENV="~/.virtualenvs/test", 此处硬编码了虚拟环境家目录, workon大约本质上去执行了activate脚本
  ```

### jupyter添加核

```
pip install ipykernel
workon env-name
python -m ipykernel install --user --name env-name --display-name env-name
```

### ssh-key

`~/.ssh` 目录结构

```
authorized_keys  # 将其他机器的公钥写入此文件中, 则其他机器可以ssh免密登录
id_rsa  # 本机私钥
id_rsa.pub  # 本机公钥
known_hosts
```

* 为本机生成 `id_rsa` 与 `id_rsa.pub` 备用

  ```bash
  ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa
  ```
* 将本机的 `id_rsa.pub` 的内容追加到服务器特定用户的 `~/.ssh/authorized_keys` 文件内，可以实现本机到服务器的远程免密登录
  * 本地 Shell 连接服务器无需输入密码。`ssh username@ip_addr`，例如：`ssh foo@172.16.83.43`
  * VScode 远程连接无需输入密码
* 将本机的 `id_rsa.pub` 的内容在 gitlab 或 github 上添加到 SSH Keys 中，则可以免密使用 ssh 进行仓库克隆、推送等操作，例如：

  ```
  git clone git@github.com:BuxianChen/notes.git
  ```

  但对 http 的方式无效，如果使用下面的方式进行 clone，在执行 push 的时候，会自动跳出一个弹出框，要求输入 github 的帐号及密码：

  ```
  git clone https://github.com/BuxianChen/notes.git
  ```

备注：要实现远程免密登陆，服务器端 `.ssh` 文件夹的权限应该为 `700`，而 `authorized_keys` 文件的权限应为 `600`

## 日志

```
nohup python -u main.py > nohup.out 2>&1 &
```

* nohup 表示关闭终端不受影响
* `-u` 表示输出到 `nohup.out` 时不进行缓存操作
* `2>&1` 表示将标准错误与标准输出（即 `print` 函数打印的内容）重定向至 `nohup.out`
* `&` 表示任务在后台进行

对于一个前台运行的程序，可以使用`ctrl+z` 快捷键暂停，或者新开一个终端，执行如下命令让它暂停

```
kill -SIGSTOP <pid>
```

暂停任务再次启动的方法为

```
jobs  # 查看后台任务
fg %1  # 将任务1放到前台继续执行
bg %1  # 将任务1放到后台继续执行
```

或者使用

```
kill -SIGCONT 
```

## 可视化

### tensorboard

参考资料：[Pytorch tutorial](https://pytorch.org/tutorials/intermediate/tensorboard_tutorial.html)、[Pytorch API](https://pytorch.org/docs/stable/tensorboard.html)

训练时将数据写入

```python
writer = SummaryWriter()
for epoch in range(4):
    for batch_idx in range(10)
        global_idx = 10 * epoch + batch_idx
        writer.add_scalar("Loss/train", loss: float, global_idx)  # 画出曲线图
        writer.add_image('a/ori_image', ori_image, global_idx)  # ori_image: (3, H, W) tensor
        writer.add_image('a/trans_image', trans_image, global_idx)  # trans_image: (3, H, W) tensor
        # 还可以写入Figure
        # writer.add_figure("matplotlib_figure", figure, global_idx)
        # 还可以对数据投影可视化
        # features: (N, C) tensor, class_labels: List[str], 长度为 N, label_img: (N, 3, H, W)
        # writer.add_embedding(features, metadata=class_labels, label_img=images)
        
        # add_video, add_audio, add_text
        # add_graph: 可视化模型(计算图)

        # add_pr_curve, add_hist: 添加PR曲线等(其实基本也可以用add_figure代替)
        # add_hparams: 这个不确定, 用于对比不同参数下实验结果?
    writer.flush()  # 将数据保存, 但不关闭
writer.close()  # 将数据保存
```

训练结束后怎么从tensorborad保存的数据中读取？

参考[stackoverflow问答](https://stackoverflow.com/questions/37304461/tensorflow-importing-data-from-a-tensorboard-tfevent-file)

```python
from tensorboard.backend.event_processing.event_accumulator import EventAccumulator
event_acc = EventAccumulator("event_file")
event_acc.Reload()
print(event_acc.Tags())

for e in event_acc.Scalars('Loss/train'):
    print(e.step, e.value)
```

### wandb（待研究）

据说这个工具相比 Tensorboard 更有优势，[参考视频](https://www.bilibili.com/video/BV17A41167WX/?spm_id_from=333.337.search-card.all.click)

## 有效利用GPU

## 小工具

### numpy 浮点数输出

```python
import numpy as np
# 输出两位小数, 抑制科学计数法输出
np.set_printoptions(precision=2, suppress=True)
```

### torch 捕获 NaN

```
x = torch.tensor([1, 2, np.nan])
torch.isnan(x)
```

### 监控 GPU 的使用

```
watch -n 1 nvidia-smi
```

或

```bash
pip install gpustat
gpustat -i 1
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://buxianchen.gitbook.io/notes/note/dl.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
