深度学习开发环境搭建docker

深度学习开发环境搭建docker

本文采用知识共享署名 4.0 国际许可协议进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,可适当缩放并在引用处附上图片所在的文章链接。

硬件环境

处理器:AMD® Ryzen 5 3600 6-core processor × 12

显卡:NVIDIA Corporation TU104 [GeForce RTX 2060]

内存:16G DDR4

硬盘:1T SSD

系统:Ubuntu 20.04.1 LTS

深度学习开发环境搭建docker

Docker

Docker 是一个开源的应用容器引擎,基于 go语言并遵从 Apache2.0 协议开源。

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

NVIDIA Docker 安装

  1. docker安装 官网上有详细的介绍:Install Docker Engine on Ubuntudocs.docker.com 或者运行下面的命令安装:
sudo apt-get update
sudo apt-get install docker.io
systemctl start docker
systemctl enable docker

可以运行这条命令检查是否安装成功:

docker version
  1. 安装NVIDIA Container Toolkit

NVIDIA/nvidia-docker

 #首先要确保已经安装了
 nvidia driver 
 # 2. 添加源 distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
 # 2. 安装并重启 sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit sudo systemctl restart docker
sudo docker run -it --name test_nvidia_docker --gpus all nvidia/cuda:11.0-base

其中最后的参数nvidia/cuda:11.0-base 是Nvidia官方的镜像,需要根据工作站主机中实际安装的cuda版本进行修改,版本可以用nvcc -V查看。

进入容器之后可以跑一下nvidia-smi命令看看:

Mon Jan 18 22:59:37 2021       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 450.102.04   Driver Version: 450.102.04   CUDA Version: 11.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  GeForce RTX 2060    Off  | 00000000:26:00.0  On |                  N/A |
|  0%   41C    P8     8W / 160W |    947MiB /  5931MiB |      5%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

Docker基本使用

启动已停止运行的容器

查看所有的容器命令如下:

$ docker ps -a
CONTAINER ID        IMAGE                   COMMAND             CREATED             STATUS                      PORTS               NAMES
e8240c787e2f        nvidia/cuda:11.0-base   "/bin/bash"         26 minutes ago      Exited (0) 52 seconds ago                       train_mnist
ae3d00922c08        nvidia/cuda:11.0-base   "/bin/bash"         37 hours ago        Exited (0) 37 hours ago                         test_nvidia_docker

使用 docker start 启动一个已停止的容器:

$ docker start ae3d00922c08 
zyh@zyh:~$ sudo docker start ae3d00922c08 
ae3d00922c08

停止一个容器

停止容器的命令如下:

$ docker stop <容器 ID>

停止的容器可以通过 docker restart 重启:

$ docker restart <容器 ID>

进入容器

在使用 -d 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:

  • docker attach
  • docker exec:推荐大家使用 docker exec 命令,因为此退出容器终端,不会导致容器的停止。

attach 命令

下面演示了使用 docker attach 命令。

$ docker attach e8240c787e2f 

注意: 如果从这个容器退出,会导致容器的停止。

exec 命令

下面演示了使用 docker exec 命令。

docker exec -it e8240c787e2f /bin/bash

注意: 如果从这个容器退出,容器不会停止,这就是为什么推荐大家使用 docker exec 的原因。

更多参数说明请使用 docker exec --help 命令查看。

导出和导入容器

导出容器

如果要导出本地某个容器,可以使用 docker export 命令。

$ docker export e8240c787e2f > train_mnist.tar

导出容器 e8240c787e2f 快照到本地文件 train_mnist.tar。

这样将导出容器快照到本地文件。

导入容器快照

可以使用 docker import 从容器快照文件中再导入为镜像,以下实例将快照文件 ubuntu.tar 导入到镜像 test/ubuntu:v1:

$ cat docker/train_mnist.tar | docker import - test/train_mnist:v1

此外,也可以通过指定 URL 或者某个目录来导入,例如:

$ docker import http://example.com/exampleimage.tgz example/imagerepo

删除容器

删除容器使用 docker rm 命令:

$ docker rm -f ae3d00922c08

下面的命令可以清理掉所有处于终止状态的容器。

$ docker container prune

拷贝本地文件到docker

  1. 查找容器

    docker ps -a
    
    CONTAINER ID        IMAGE                   COMMAND             CREATED             STATUS              PORTS               NAMES
    e8240c787e2f        nvidia/cuda:11.0-base   "/bin/bash"         42 minutes ago      Up 8 minutes                            train_mnist
    
  2. 确定我们的容器名,并获取容器长ID

    docker inspect -f '{{.ID}}' train_mnist
    
    zyh@zyh:~/temp$ sudo docker inspect -f '{{.ID}}' train_mnist
    e8240c787e2fde06a3f1066db71bc63cb52514c3cb0175d51713f248a2e2b56c
    
  3. 复制文件

    sudo docker cp /home/zyh/temp/cuda_11.0.2_450.51.05_linux.run e8240c787e2fde06a3f1066db71bc63cb52514c3cb0175d51713f248a2e2b56c:/home/zyh
    

docker 训练模型

  1. 创建docker

     sudo docker run  -it  --name train_mnist \
     -v /etc/timezone:/etc/timezone \
     -v /etc/localtime:/etc/localtime \
     -v /home/zyh/WorkSpace/_share:/home/workspace/_share  \
     --gpus all nvidia/cuda:11.0-base
    
  2. 查看 nvidia 驱动

    nvidia-smi
    
  3. 安装 cuda

    sudo sh ./cuda_11.0.2_450.51.05_linux.run
    

    配置环境变量

    vim ~/.bashrc
    
    export CUDA_HOME=/usr/local/cuda-11.0
    export LD_LIBRARY_PATH=${CUDA_HOME}/lib64
    export PATH=${CUDA_HOME}/bin:${PATH}
    
    source ~/.bashrc
    

    查看安装版本

    nvcc -V
    
  4. 安装 CuDNN

     tar -xzvf cudnn-11.0-linux-x64-v8.0.5.39.tgz
     
     sudo cp cuda/lib64/* /usr/local/cuda-11.0/lib64/
     sudo cp cuda/include/* /usr/local/cuda-11.0/include/
    

    查看 CUDNN的版本

    cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2
    
  5. 安装conda

    chmod +x Anaconda3-2020.11-Linux-x86_64.sh
    
    ./Anaconda3-2020.11-Linux-x86_64.sh
    
  6. 测试

    创建 python3.8+pytorch1.7+cuda11.0的虚拟环境

    conda create --name python_38-pytorch_1.7.0 python=3.8
    

    进入环境

    conda activate python_38-pytorch_1.7.0
    

    安装pytorch

    pip install torch==1.7.0+cu110 torchvision==0.8.1+cu110 torchaudio===0.7.0 -f https://download.pytorch.org/whl/torch_stable.html
    

    测试文件

    
    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
    
    
    class Net(nn.Module):
        def __init__(self):
            super(Net, self).__init__()
            self.conv1 = nn.Conv2d(1, 20, 5, 1)
            self.conv2 = nn.Conv2d(20, 50, 5, 1)
            self.fc1 = nn.Linear(4 * 4 * 50, 500)
            self.fc2 = nn.Linear(500, 10)
    
        def forward(self, x):
            x = F.relu(self.conv1(x))
            x = F.max_pool2d(x, 2, 2)
            x = F.relu(self.conv2(x))
            x = F.max_pool2d(x, 2, 2)
            x = x.view(-1, 4 * 4 * 50)
            x = F.relu(self.fc1(x))
            x = self.fc2(x)
            return F.log_softmax(x, dim=1)
    
    
    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()))
    
    
    def test(args, 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)
                # sum up batch loss
                test_loss += F.nll_loss(output, target, reduction='sum').item()
                # get the index of the max log-probability
                pred = output.argmax(dim=1, keepdim=True)
                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():
        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=10, metavar='N',
                            help='number of epochs to train (default: 10)')
        parser.add_argument('--lr', type=float, default=0.01, metavar='LR',
                            help='learning rate (default: 0.01)')
        parser.add_argument('--momentum', type=float, default=0.5, metavar='M',
                            help='SGD momentum (default: 0.5)')
        parser.add_argument('--no-cuda', action='store_true', default=False,
                            help='disables CUDA training')
        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()
        torch.manual_seed(args.seed)
        device = torch.device("cuda" if use_cuda else "cpu")
        kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}
        train_loader = torch.utils.data.DataLoader(
            datasets.MNIST('./data', train=True, download=True,
                           transform=transforms.Compose([
                               transforms.ToTensor(),
                               transforms.Normalize((0.1307,), (0.3081,))
                           ])),
            batch_size=args.batch_size, shuffle=True, **kwargs)
        test_loader = torch.utils.data.DataLoader(
            datasets.MNIST('./data', train=False, transform=transforms.Compose([
                transforms.ToTensor(),
                transforms.Normalize((0.1307,), (0.3081,))
            ])),
            batch_size=args.test_batch_size, shuffle=True, **kwargs)
    
        model = Net().to(device)
        optimizer = optim.SGD(model.parameters(), lr=args.lr,
                              momentum=args.momentum)
    
        for epoch in range(1, args.epochs + 1):
            train(args, model, device, train_loader, optimizer, epoch)
            test(args, model, device, test_loader)
    
        if (args.save_model):
            torch.save(model.state_dict(), "mnist_cnn.pt")
    
    
    if __name__ == '__main__':
        main()
    
    
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

002237

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值