Win10+WSL+Ubuntu 22.04+VSCode cuda、cudnn、pytorch安装配置

1 概述

1.1 写在前面

上一篇文章搞了一下WSL,但是只是用Ubuntu给texlive套了个壳,虽然texlive安装好就占了8.5个G(苦笑),还是感觉有点浪费这个系统。因为本人主要搞机器学习,所以又去研究了一下WSL能不能提升网络训练的速度,结果还真有up做过测试,可以看这个视频。训练mnist大概能节省一半的时间,这个提升还是挺有诱惑力的,于是花时间折腾了一下。

1.2 前置工作

  • 安装WSL 2
  • 安装Ubuntu 22.04
  • 安装Windows Terminal(可选)

上述软件/工具的安装教程在我上一篇博客中已给出,地址是这里

2 环境配置

系统版本:Windows 10 专业版 22H2 内部版本19045.4651
WSL:第2版
Linux子系统:Ubuntu 22.04.3 LTS
cuda驱动版本:12.2.138
cuda toolkit:12.1 for Linux WSL-Ubuntu 2.0 x86_64
cudnn:8.9.0 for cuda 12.x
python:3.10
pytorch:2.3.0+cu121
VSCode:1.91.0

尤其要注意cuda、toolkit、cudnn以及pytorch之间的版本对应关系,这个自己查吧,其实挺简单的。

3 安装流程

3.1 anaconda安装

3.1.1 anaconda下载

进入官网,选择最新版本anaconda下载

在这里插入图片描述

下载完成是一个后缀为.sh的文件,我们将它移动到ubuntu的/home/username文件夹下
打开文件资源管理器,左侧侧栏最下方有个Linux选项,这就是ubuntu系统的内部目录(十分的方便啊),找到对应路径,复制进去

在这里插入图片描述

3.1.2 安装anaconda

输入以下命令安装anaconda,注意版本是否一致

bash Anaconda3-2024.06-1-Linux-x86_64.sh

然后一直按着Enter,过一下用户协议,输入yes,接受协议,然后安装位置默认即可

在这里插入图片描述

是否初始化,输入yes
然后把当前shell关闭,重新启动一下,输入conda -V测试是否正常输出版本号

在这里插入图片描述

3.1.3 创建虚拟环境

输入以下命令创建虚拟环境,用于安装pytorch

conda create -n torch230 python=3.10

激活环境,测试是否安装成功

在这里插入图片描述

3.2 cuda toolkit 安装与配置

3.2.1 cuda toolkit 安装

进入NVIDIA官网cuda toolkit对应版本的下载界面,选择Linux/X86_64/WSL-Ubuntu/2.0/deb[local]

在这里插入图片描述

依次复制以下命令进行安装

wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin
sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/12.1.0/local_installers/cuda-repo-wsl-ubuntu-12-1-local_12.1.0-1_amd64.deb
sudo dpkg -i cuda-repo-wsl-ubuntu-12-1-local_12.1.0-1_amd64.deb
sudo cp /var/cuda-repo-wsl-ubuntu-12-1-local/cuda-*-keyring.gpg /usr/share/keyrings/
sudo apt-get update
sudo apt-get -y install cuda

3.2.2 环境变量配置

输入sudo vim ~/.bashrc,打开环境变量配置文件,将光标调到最后,添加以下两条环境变量

export PATH=/usr/local/cuda-12.1/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

输入source ~/.bashrc命令,使环境变量立即生效。
配置完成之后,重新启动shell,执行nvcc -V指令,检查是否安装成功

在这里插入图片描述

3.3 cudnn安装

3.3.1 下载对应版本的cudnn

进入NVIDIA官网cuda toolkit对应版本的下载界面,选择第二个下载

在这里插入图片描述

3.3.2 cudnn安装

cudnn没有严格意义上的安装过程,只需要将lib和include两个文件夹里的文件移动到对应路径即可
首先,将下载的cudnn压缩包移动到/home/username/路径下,运行以下命令解压

sudo tar -xvf cudnn-linux-x86_64-8.9.0.131_cuda12-archive.tar.xz

进入解压后的目录,依次输入以下命令进行拷贝

cd cudnn-linux-x86_64-8.9.0.131_cuda12-archive/lib
sudo cp -r * /usr/local/cuda-12.1/lib64
cd ..
cd include
sudo cp -r * /usr/local/cuda-12.1/include

然后更改一下目录权限

sudo chmod a+r /usr/local/cuda-12.1/include/cudnn*
sudo chmod a+r /usr/local/cuda-12.1/lib64/libcudnn*

检查是否安装成功

cat /usr/local/cuda-12.1/include/cudnn_version.h | grep CUDNN_MAJOR -A 2

在这里插入图片描述

3.4 pytorch安装

进入pytorch官网,选择对应版本的安装命令

# 激活环境
conda activate torch230
# 安装pytorch
pip install torch==2.3.0 torchvision==0.18.0 torchaudio==2.3.0 --index-url https://download.pytorch.org/whl/cu121

安装完成!

在这里插入图片描述

测试一下

import torch
print(torch.__version__)
print(torch.cuda.is_available())

在这里插入图片描述

完成!

3.5 vscode连接该环境

3.5.1 连接过程

打开vscode,按Ctrl+Shift+P,打开命令输入框,输入wsl,选择WSL: 在新窗口中连接到WSL,vscode会自动连接完成配置
在这里插入图片描述

另外,为了在vscode中运行python代码,需要在扩展商店下载相关插件,包括isort、Python、Pylance、Python Debugger,该过程耗时较长,需要多次重新加载窗口

3.5.2 mnist数据集测试

点击图中所示位置进行环境选择,选择torch230环境

在这里插入图片描述

以下是pytorch官方的示例代码,仅修改了数据读取的工作线程数以及添加了时间统计。在ubuntu中新建mnist.py文件,并复制粘贴该代码,使用命令python mnist.py运行

import argparse
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.optim.lr_scheduler import StepLR
import time


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.dropout1 = nn.Dropout(0.25)
        self.dropout2 = nn.Dropout(0.5)
        self.fc1 = nn.Linear(9216, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = F.relu(x)
        x = self.conv2(x)
        x = F.relu(x)
        x = F.max_pool2d(x, 2)
        x = self.dropout1(x)
        x = torch.flatten(x, 1)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.dropout2(x)
        x = self.fc2(x)
        output = F.log_softmax(x, dim=1)
        return output


def train(args, model, device, train_loader, optimizer, epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        output = model(data)
        loss = F.nll_loss(output, target)
        loss.backward()
        optimizer.step()
        if batch_idx % args.log_interval == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                100. * batch_idx / len(train_loader), loss.item()))
            if args.dry_run:
                break


def test(model, device, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            test_loss += F.nll_loss(output, target, reduction='sum').item()  # sum up batch loss
            pred = output.argmax(dim=1, keepdim=True)  # get the index of the max log-probability
            correct += pred.eq(target.view_as(pred)).sum().item()

    test_loss /= len(test_loader.dataset)

    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))


def main():
    # Training settings
    parser = argparse.ArgumentParser(description='PyTorch MNIST Example')
    parser.add_argument('--batch-size', type=int, default=64, metavar='N',
                        help='input batch size for training (default: 64)')
    parser.add_argument('--test-batch-size', type=int, default=1000, metavar='N',
                        help='input batch size for testing (default: 1000)')
    parser.add_argument('--epochs', type=int, default=14, metavar='N',
                        help='number of epochs to train (default: 14)')
    parser.add_argument('--lr', type=float, default=1.0, metavar='LR',
                        help='learning rate (default: 1.0)')
    parser.add_argument('--gamma', type=float, default=0.7, metavar='M',
                        help='Learning rate step gamma (default: 0.7)')
    parser.add_argument('--no-cuda', action='store_true', default=False,
                        help='disables CUDA training')
    parser.add_argument('--no-mps', action='store_true', default=False,
                        help='disables macOS GPU training')
    parser.add_argument('--dry-run', action='store_true', default=False,
                        help='quickly check a single pass')
    parser.add_argument('--seed', type=int, default=1, metavar='S',
                        help='random seed (default: 1)')
    parser.add_argument('--log-interval', type=int, default=10, metavar='N',
                        help='how many batches to wait before logging training status')
    parser.add_argument('--save-model', action='store_true', default=False,
                        help='For Saving the current Model')
    args = parser.parse_args()
    use_cuda = not args.no_cuda and torch.cuda.is_available()
    use_mps = not args.no_mps and torch.backends.mps.is_available()

    torch.manual_seed(args.seed)

    if use_cuda:
        device = torch.device("cuda")
    elif use_mps:
        device = torch.device("mps")
    else:
        device = torch.device("cpu")

    train_kwargs = {'batch_size': args.batch_size}
    test_kwargs = {'batch_size': args.test_batch_size}
    if use_cuda:
        cuda_kwargs = {'num_workers': 5,
                       'pin_memory': True,
                       'shuffle': True}
        train_kwargs.update(cuda_kwargs)
        test_kwargs.update(cuda_kwargs)

    transform=transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
        ])
    dataset1 = datasets.MNIST('../data', train=True, download=True,
                       transform=transform)
    dataset2 = datasets.MNIST('../data', train=False,
                       transform=transform)
    train_loader = torch.utils.data.DataLoader(dataset1,**train_kwargs)
    test_loader = torch.utils.data.DataLoader(dataset2, **test_kwargs)

    model = Net().to(device)
    optimizer = optim.Adadelta(model.parameters(), lr=args.lr)

    scheduler = StepLR(optimizer, step_size=1, gamma=args.gamma)
    start_time = time.time()
    for epoch in range(1, args.epochs + 1):
        train(args, model, device, train_loader, optimizer, epoch)
        test(model, device, test_loader)
        scheduler.step()
    end_time = time.time()
    print(f"Total time taken: {end_time - start_time} seconds")

    if args.save_model:
        torch.save(model.state_dict(), "mnist_cnn.pt")


if __name__ == '__main__':
    main()

3.5.3 踩坑及处理

在这里插入图片描述

运行mnist.py报错Could not load library libcudnn_cnn_train.so.8. Error: /usr/local/cuda-12.1/lib64/libcudnn_cnn_train.so.8: undefined symbol: _ZN5cudnn3cnn5infer22queryClusterPropertiesERPhS3_, version libcudnn_cnn_infer.so.8,这是由于使用pip命令安装pytorch2.3+cu121时,默认会一起安装pytorch提供的cudnn,从而与我们前面安装的cudnn产生了冲突,解决方案有两个:

  1. 把我们自己安装的cudnn删掉,并注释掉环境变量(那我前面不是白干了,我可不受这委屈!)
  2. 把pytorch提供的cudnn卸载

这里介绍第二种,首先,输入命令pip list

在这里插入图片描述

可以看到,pytorch提供的cudnn是8.9.2.26,与我们安装的8.9.0是冲突的,我们可以使用命令pip uninstall nvidia-cudnn-cu12卸载

随后再次进行测试
在这里插入图片描述
运行成功!
可以看到,运行时间为64秒,笔者自己测试在Windows上运行需要170秒,快了大约三倍,还是不错的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值