NVIDIA 优化框架

深度学习框架容器用户指南

摘要

本指南详细概述了容器,并提供了有关拉取和运行容器以及自定义和扩展容器的逐步说明。


容器封装了应用程序及其库和其他依赖项,以提供应用程序和服务的可重现和可靠的执行,而无需完整虚拟机的开销。

自 Docker 19.03 版本起,NVIDIA GPU 在 Docker 运行时中得到原生支持。 这意味着不再需要 nvidia-docker2 提供的特殊运行时。

Docker 镜像
Docker 镜像只是您在 Docker 容器中运行的软件(包括文件系统和参数)。
Docker 容器
Docker 容器是 Docker 镜像的一个实例。一个 Docker 容器为每个容器部署单个应用程序或服务。

1.1. 什么是 Docker 容器?

Docker 容器是一种机制,用于将 Linux 应用程序与其所有库、数据文件和环境变量捆绑在一起,以便在任何 Linux 系统上运行以及在同一主机上的实例之间,执行环境始终相同。

与具有自己隔离内核的 VM 不同,容器使用主机系统内核。因此,来自容器的所有内核调用都由主机系统内核处理。DGX™ 系统使用 Docker 容器作为部署深度学习框架的机制。

Docker 容器由层组成。这些层组合在一起以创建容器。您可以将层视为中间镜像,它们为整个容器添加了一些功能。如果您通过 DockerFile(请参阅 构建容器)更改了某个层,则 Docker 会重建该层和所有后续层,但不会重建未受构建影响的层。这减少了创建容器的时间,并允许您保持容器的模块化。

Docker 在系统上保留层的一个副本方面也做得很好。这节省了空间,并大大降低了“版本偏差”的可能性,从而避免了本应相同的层被重复。

Docker 容器是 Docker 镜像的运行实例。

1.2. 为什么要使用容器?

使用容器的众多好处之一是,您可以将应用程序、依赖项和环境变量一次性安装到容器镜像中;而不是在您运行的每个系统上都安装。此外,使用容器的主要好处还包括:

  • 将您的应用程序、依赖项和环境变量一次性安装到容器镜像中;而不是在您运行的每个系统上都安装。
  • 不会与其他人安装的库发生冲突的风险。
  • 容器允许在同一服务器上使用多个不同的深度学习框架,这些框架可能具有冲突的软件依赖性。
  • 将应用程序构建到容器中后,您可以在许多其他地方(尤其是服务器)运行它,而无需安装任何软件。
  • 传统的加速计算应用程序可以容器化并部署在更新的系统上,无论是在本地还是在云端。
  • 可以将特定的 GPU 资源分配给容器,以实现隔离和更好的性能。
  • 您可以轻松地跨不同环境共享、协作和测试应用程序。
  • 可以并发运行给定深度学习框架的多个实例,每个实例分配一个或多个特定的 GPU。
  • 容器可以用于解决应用程序之间的网络端口冲突,方法是在启动容器时将容器端口映射到特定的外部可见端口。

1.3. 容器的“Hello World”

为了确保您可以访问 NVIDIA 容器,请从 Docker 命令的众所周知的“hello world”开始。

对于 DGX 系统,只需登录系统即可。有关当前支持的 DGX 系统列表,请参阅框架支持矩阵。对于 NGC,请查阅 NGC 文档,了解有关您的特定云提供商的详细信息。通常,您将使用 NVIDIA 深度学习镜像通过云提供商启动云实例。实例启动后,登录到该实例。

接下来,您可以发出 docker --version 命令来列出 DGX 系统的版本。此命令的输出会告诉您系统上 Docker 的版本 (18.06.3-ce, build 89658be)。

在任何时候,如果您不确定 Docker 命令,请发出 docker --help 命令。

1.4. 登录 Docker

如果您有 DGX 系统,则首次登录时,您需要设置对 NVIDIA NGC 容器注册表 (https://ngc.nvidia.com) 的访问权限。有关更多信息,请参阅 NGC 用户指南

1.5. 列出 Docker 镜像

通常,您要做的第一件事之一是获取本地计算机上当前可用的所有 Docker 镜像的列表。发出 docker pull 命令会将 Docker 镜像从存储库下载到您的本地系统。发出 docker images 命令以列出服务器上的镜像。您的屏幕将类似于以下内容

复制
已复制!
            

REPOSITORY TAG IMAGE ID mxnet-dec latest 65a48ellda96 <none> <none> bfc4512ca5f2 nvcr.io/nvidian_general/adlr_pytorch resumes al34a09668a8 <none> <none> 0f4ab6d62241 <none> <none> 97274da5c898 nvcr.io/nvidian_sas/games-libcchem cuda10 3dcl3f8347f9 nvidia/cuda latest 614dcdafa05c ubuntu latest d355ed3537e9 deeper_photo latest 9326345l4d5a nvidia/cuda 10.0-devel-centos7 6e3e5b71176e nvcr.io/nvidia/tensorflow 19.03 56f2980ble37 nvidia/cuda 10.0-cudnn7-devel-ubuntu16.04 22afb0578249 nvidia/cuda 10.0-devel a760a0cfca82 mxnet/python gpu 7e7c9176319c deep_photo latest ef4510510506 <none> <none> 9124236672fe nvcr.io/nvidia/cuda 10.0-cudnn7-devel-ubuntu18.04 02910409eb5d nvcr.io/nvidia/tensorflow 19.05 9dda0d5c344f


在此示例中,有一些 Docker 容器已被拉取到此系统。每个镜像都列出了其 标签、相应的 镜像 ID,也称为 容器版本。还有另外两列列出了容器创建时间(大约)以及镜像的大约大小(GB)。这些列已被裁剪以提高可读性。

注意

命令的输出将有所不同。


在任何时候,如果您需要帮助,请发出 docker images --help 命令。


关于此任务

NVIDIA 还开发了一组容器镜像,以确保您的应用程序获得最佳性能。

NGC 容器充分利用了 NVIDIA GPU。有关更多信息,请参阅 NGC Catalog User Guide

2.1. Docker 最佳实践

您可以在任何与 Docker 兼容的平台上运行 Docker 容器,从而使您可以将应用程序移动到所需的任何位置。容器是平台无关的,因此也是硬件无关的。为了获得最佳性能并充分利用 NVIDIA GPU 的强大性能,需要特定的内核模块和用户级库。NVIDIA GPU 引入了一些复杂性,因为它们需要内核模块和用户级库才能运行。

使用容器时,解决此复杂性的一种方法是在容器中安装 NVIDIA 驱动程序,并映射与 NVIDIA GPU 对应的字符设备,例如 /dev/nvidia0。为了使其工作,主机(运行容器的系统)上的驱动程序必须与容器中安装的驱动程序版本匹配。这种方法大大降低了容器的可移植性。

2.2. docker exec

有时您需要连接到正在运行的容器。您可以使用 docker exec 命令连接到正在运行的容器以运行命令。您可以使用 bash 命令启动交互式命令行终端或 bash shell。

复制
已复制!
            

$ docker exec -it <CONTAINER_ID_OR_NAME> bash


例如,使用以下命令启动 PyTorch 深度学习 GPU 训练系统™ (DIGITS) 容器

复制
已复制!
            

docker run --gpus all -d --name test-pyt \ -u $(id -u):$(id -g) -e HOME=$HOME -e USER=$USER -v $HOME:$HOME \ nvcr.io/nvidia/pytorch:24.05-py3


容器运行后,您现在可以连接到容器实例。

复制
已复制!
            

$ docker exec -it test-pyt bash

注意

test-pyt 是容器的名称。如果您没有特别命名容器,则必须使用容器 ID。

重要提示

通过使用 docker exec,您可以执行代码片段、脚本或以交互方式连接到容器,这使得 docker exec 命令非常有用。


有关 docker exec 命令的详细用法,请参阅 docker exec

2.3. nvcr.io

构建深度学习框架可能需要大量工作,并且可能非常耗时。此外,这些框架每周甚至每天都在更新。最重要的是,需要优化和调整框架以适应 GPU。NVIDIA 创建了一个名为 nvcr.io 的 Docker 存储库,其中深度学习框架经过调整、优化、测试并容器化以供您使用。

NVIDIA 每月为框架创建一组更新的 Docker 容器。容器中包含源代码(这些是开源框架)、用于构建框架的脚本、用于创建基于这些容器的容器的 Dockerfile、包含有关特定容器文本的 markdown 文件,以及用于拉取可用于测试或学习的数据集的工具和脚本。购买 DGX 系统的客户可以访问此存储库以推送容器(存储容器)。

要开始使用 DGX 系统,您需要创建一个系统管理员帐户以访问 nvcr.io。此帐户应被视为管理员帐户,以便用户无法访问它。创建此帐户后,系统管理员可以为属于该帐户的项目创建帐户。然后,他们可以授予用户对这些项目的访问权限,以便他们可以存储或共享他们创建的任何容器。

2.4. 构建容器

关于此任务

如果您拥有 DGX 系统,则可以将容器构建并存储在 nvcr.io 注册表中作为您帐户中的项目(例如,除非您授予其他人访问权限,否则没有人可以访问该容器)。

本文档的本节适用于一般的 Docker 容器。您也可以将这种通用方法用于您自己的 Docker 存储库,但请注意细节。使用 DGX 系统,您可以:

  1. 从头开始创建容器
  2. 基于现有的 Docker 容器创建容器
  3. 基于 nvcr.io 中的容器创建容器。

这三种方法中的任何一种都是有效且可行的,但是,由于目标是在具有 GPU 的系统上运行容器,因此可以合理地假设应用程序将使用 GPU。此外,这些容器已经针对 GPU 进行了调整。它们也都包括重建容器所需的 GPU 库、配置文件和工具。

重要提示

基于这些假设,建议您从 nvcr.io 中的容器开始。


nvcr.io 中的现有容器应作为起点。例如,将使用 TensorFlow 24.05 容器,并将 Octave 添加到容器中,以便可以完成一些结果的后处理。

步骤

  1. 将容器从 NGC 容器注册表拉取到服务器。请参阅 拉取容器
  2. 在服务器上,创建一个名为 mydocker 的子目录。
    注意

    这是一个任意目录名。

  3. 在此目录内,创建一个名为 Dockerfile 的文件(大小写很重要)。这是 Docker 在创建容器时查找的默认名称。Dockerfile 应类似于以下内容
    复制
    已复制!
                

    [username ~]$ mkdir mydocker [username ~]$ cd mydocker [username mydocker]$ vi Dockerfile [username mydocker]$ more Dockerfile FROM nvcr.io/nvidia/tensorflow:24.05-tf2-py3 RUN apt-get update RUN apt-get install -y octave [username mydocker]$

    Dockerfile 中有三行。
    • Dockerfile 中的第一行告诉 Docker 从容器 nvcr.io/nvidia/tensorflow:24.05-tf2-py3 开始。这是新容器的基础容器。
    • Dockerfile 中的第二行对容器执行软件包更新。它不会更新容器中的任何应用程序,但会更新 apt-get 数据库。这是在我们在容器中安装新应用程序之前所必需的。
    • Dockerfile 中的第三行也是最后一行告诉 Docker 使用 apt-get 将软件包 octave 安装到容器中。

    用于创建容器的 Docker 命令是

    复制
    已复制!
                

    $ docker build -t nvcr.io/nvidian_sas/tensorflow_octave:24.05_with_octave

    注意

    此命令使用默认文件 Dockerfile 来创建容器。

    该命令以 docker build 开头。-t 选项为此新容器创建一个标签。请注意,该标签指定了 nvcr.io 存储库中要存储容器的项目。例如,项目 nvidian_sas 与存储库 nvcr.io 一起使用。

    项目可以由控制对 nvcr.io 访问权限的本地管理员创建,或者他们可以授予您创建项目的权限。您可以在此处存储您的特定容器,甚至可以与您的同事共享这些容器。

    复制
    已复制!
                

    [username mydocker]$ docker build -t nvcr.io/nvidian_sas/tensorflow_octave:24.05_with_octave. Sending build context to Docker daemon 2.048kB Step 1/3 : FROM nvcr.io/nvidia/tensorflow:24.05-tf2-py3 –--> 56f2980ble37 Step 2/3 : RUN apt-get update –--> Running in 69cffa7bbadd Get:1 http://security.ubuntu.com/ubuntu xenial-security InRelease [102 kB] Get:2 http://ppa.launchpad.net/openjdk-r/ppa/ubuntu xenial InRelease [17.5 kB] Get:3 http://archive.ubuntu.com/ubuntu xenial InRelease [247 kB] Get:4 http://ppa.launchpad.net/openjdk-r/ppa/ubuntu xenial/main amd64 Packages [7096 B] Get:5 http://security.ubuntu.com/ubuntu xenial-security/universe Sources [42.0 kB] Get:6 http://security.ubuntu.com/ubuntu xenial-security/main amd64 Packages [380 kB] Get:7 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB] Get:8 http://security.ubuntu.com/ubuntu xenial-security/restricted amd64 Packages [12.8 kB] Get:9 http://security.ubuntu.com/ubuntu xenial-security/universe amd64 Packages [178 kB] Get:10 http://security.ubuntu.com/ubuntu xenial-security/multiverse amd64 Packages [2931 B] Get:11 http://archive.ubuntu.com/ubuntu xenial-backports InRelease [102 kB] Get:12 http://archive.ubuntu.com/ubuntu xenial/universe Sources [9802 kB] Get:13 http://archive.ubuntu.com/ubuntu xenial/main amd64 Packages [1558 kB] Get:14 http://archive.ubuntu.com/ubuntu xenial/restricted amd64 Packages [14.1 kB] Get:15 http://archive.ubuntu.com/ubuntu xenial/universe amd64 Packages [9827 kB]

    在上面显示的 docker build … 命令的简短输出中,Dockerfile 中的每一行都是一个 步骤。在屏幕截图中,您可以看到第一步和第二步(命令)。Docker 将这些命令回显到标准输出 (stdout),以便您可以观看它的执行过程,或者您可以捕获输出以用于文档记录。

    构建镜像后,请记住我们尚未将镜像存储在存储库中,因此,它是一个 docker image。Docker 在最后将镜像 ID 输出到 stdout。它还会告诉您是否已成功创建并标记镜像。

    如果您在输出末尾没有看到 Successfully ...,请检查您的 Dockerfile 是否有错误(也许尝试简化它),或者尝试一个非常简单的 Dockerfile 以确保 Docker 正常工作。

  4. 验证 Docker 是否成功创建了镜像。
    复制
    已复制!
                

    $ docker images

    例如
    复制
    已复制!
                

    [username mydocker]$ docker images REPOSITORY TAG IMAGE ID CREATED nvcr.io/nvidian_sas/tensorflow_octave 24.05_with_octave 67c448c6fe37 About a minute ago nvcr.io/nvidian_general/adlr_pytorch resumes 17f2398a629e 47 hours ago <none> <none> 0c0f174e3bbc 9 days ago nvcr.io/nvidian_sas/pushed-hshin latest c026c5260844 9 days ago <none> <none> al34a09668a8 2 weeks ago <none> <none> 0f4ab6d62241 2 weeks ago nvidia/cuda 10.0-cudnn7-devel-ubuntu16.04 a995cebf5782 2 weeks ago keras_ae latest 92ab2bed8348 3 weeks ago nvidia/cuda latest 6l4dcdafa05c 3 weeks ago ubuntu latest d355ed3537e9 3 weeks ago deeper_photo latest f4e395972368 4 weeks ago <none> <none> 0e8208a5e440 4 weeks ago nvcr.io/nvidia/tensorflow 19.03 56f2980ble37 5 weeks ago mxnet/python gpu 7e7c9176319c 6 weeks ago deep_photo latest ef4510510506 7 weeks ago <none> <none> 9124236672fe 8 weeks ago nvcr.io/nvidia/cuda 10.0-cudnn7-devel-ubuntu18.04 02910409eb5d 8 weeks ago nvcr.io/nvidia/tensorflow 19.03 9dda0d5c344f 2 months ago nvcr.io/nvidia/tensorflow 19.03 121558cb5849 3 months ago

    第一个条目是新镜像(大约 1 分钟前)。

  5. 将镜像推送到存储库中,创建容器。
    复制
    已复制!
                

    docker push <name of image>

    例如
    复制
    已复制!
                

    [username mydocker]$ docker push nvcr.io/nvidian_sas/tensorflow_octave:24.05_with_octave The push refers to a repository [nvcr.io/nvidian_sas/tensorflow_octave] lb8lf494d27d: Image successfully pushed 023cdba2c5b6: Image successfully pushed 8dd41145979c: Image successfully pushed 7cbl6b9b8d56: Image already pushed, skipping bd5775db0720: Image already pushed, skipping bc0c86a33aa4: Image already pushed, skipping cc739l3099f7: Image already pushed, skipping d49f214775fb: Image already pushed, skipping 5d6703088aa0: Image already pushed, skipping 7822424b3bee: Image already pushed, skipping e999e9a30273: Image already pushed, skipping e33eae9b4a84: Image already pushed, skipping 4a2ad165539f: Image already pushed, skipping 7efc092a9b04: Image already pushed, skipping 914009c26729: Image already pushed, skipping 4a7ea614f0c0: Image already pushed, skipping 550043e76f4a: Image already pushed, skipping 9327bc0l58ld: Image already pushed, skipping 6ceab726bc9c: Image already pushed, skipping 362a53cd605a: Image already pushed, skipping 4b74ed8a0e09: Image already pushed, skipping lf926986fb96: Image already pushed, skipping 832ac06c43e0: Image already pushed, skipping 4c3abd56389f: Image already pushed, skipping d8b353eb3025: Image already pushed, skipping f2e85bc0b7bl: Image already pushed, skipping fc9ele5e38f7: Image already pushed, skipping f39a3f9c4559: Image already pushed, skipping 6a8bf8c8edbd: Image already pushed, skipping Pushing tag for rev [67c448c6fe37] on {https://nvcro.io/vl/repositories/nvidian_sas/tensorflow_octave

    上面的示例代码是在 docker push … 命令将镜像推送到存储库以创建容器之后。此时,您应该登录到 NGC 容器注册表 https://ngc.nvidia.com 并查看您的项目下是否有该容器。

    如果您在项目中没有看到该容器,请确保镜像上的标签与存储库中的位置匹配。如果由于某种原因推送失败,请重试,以防您的系统与容器注册表 (nvcr.io) 之间存在通信问题。

    为了确保容器在存储库中,我们可以将其拉取到服务器并运行它。作为测试,首先使用命令 docker rmi … 从您的 DGX 系统中删除镜像。然后,使用 docker pull … 将容器拉取到服务器。请注意,octave 提示符出现了,因此它已安装并在本次测试范围内正常运行。

2.5. 使用和挂载文件系统

使用 Docker 的基本方面之一是在 Docker 容器内部挂载文件系统。这些文件系统可以包含框架的输入数据,甚至是在容器中运行的代码。Docker 容器有自己的内部文件系统,该文件系统与主机其余部分的文件系统是分开的。

重要提示

您可以根据需要从外部将数据复制到容器文件系统中。但是,将外部文件系统挂载到容器中要容易得多。


挂载外部文件系统是使用 docker run --gpus 命令和 -v 选项完成的。例如,以下命令挂载两个文件系统

复制
已复制!
            

$ docker run --gpus all --rm -ti ... -v $HOME:$HOME \ -v /datasets:/digits_data:ro \ ...


除了卷之外,大多数命令已被删除。此命令将用户的主目录从外部文件系统挂载到容器中的主目录 (-v $HOME:$HOME)。它还从主机中获取 /datasets 目录,并将其挂载到容器内的 /digits_data 上 (-v /datasets:/digits_data:ro)。

记住

用户具有 Docker 的 root 权限,因此您可以将主机系统中的几乎任何内容挂载到容器中的任何位置。


对于此特定命令,卷命令采用以下形式

复制
已复制!
            

-v <External FS Path>:<Container FS Path>(options) \


该选项的第一部分是外部文件系统的路径。为了确保其正常工作,最好使用完全限定路径 (FQP)。对于容器内的挂载点 <容器 FS 路径> 也是如此。

在最后一个路径之后,可以在括号 () 中使用各种选项。在上面的示例中,第二个文件系统在容器内以只读 (ro) 方式挂载。有关 -v 选项的各种选项,请参阅此处

DGX™ 系统和 Docker 容器使用 Overlay2 存储驱动程序将外部文件系统挂载到容器文件系统上。Overlay2 是一个联合挂载文件系统驱动程序,允许您组合多个文件系统,以便所有内容看起来都组合到一个文件系统中。它创建文件系统的联合,而不是交集。


关于此任务

在您可以从 NGC 容器注册表中拉取容器之前,您必须安装 Docker。对于 DGX 用户,这在 准备使用 NVIDIA 容器 中进行了解释。

对于 DGX 以外的用户,请按照 NGC 用户指南 进行操作。您可以在四个存储库中找到 NGC docker 容器。

nvcr.io/nvidia
深度学习框架容器存储在 nvcr.io/nvidia 存储库中。
nvcr.io/hpc
HPC 容器存储在 nvcr.io/hpc 存储库中。
nvcr.io/nvidia-hpcvis
HPC 可视化容器存储在 nvcr.io/nvidia-hpcvis 存储库中。
nvcr.io/partner
合作伙伴容器存储在 nvcr.io/partner 存储库中。目前,合作伙伴容器专注于深度学习或机器学习,但这并不意味着它们仅限于这些类型的容器。

3.1. 关键概念

要发出拉取和运行命令,请确保您熟悉以下概念。拉取命令类似于

复制
已复制!
            

docker pull nvcr.io/nvidia/tensorflow:24.05-tf2-py3


运行命令类似于

复制
已复制!
            

docker run --gpus all -it --rm –v local_dir:container_dir nvcr.io/nvidia/tensorflow:<xx.xx>-tf2-py3

注意

基本命令 docker run --gpu all 假定您的系统已安装 Docker 19.03-CE 和 NVIDIA 运行时软件包。有关早期版本 Docker 使用的命令,请参阅 为 NGC 容器启用 GPU 支持 部分。


以下概念描述了构成这两个命令的单独属性。

nvcr.io
容器注册表的名称,NGC 容器注册表的名称为 nvcr.io
nvidia
注册表中包含深度学习容器的空间的名称。对于 NVIDIA 提供的容器,注册表空间为 nvidia
-it
您要以交互模式运行容器。
--rm
您希望在完成后删除容器。
–v
您要挂载目录。
local_dir
您要从容器内部访问的主机系统中的目录或文件(绝对路径)。例如,以下路径中的 local_dir/home/jsmith/data/mnist
复制
已复制!
            

-v /home/jsmith/data/mnist:/data/mnist

如果您在容器内部,例如,使用命令 ls /data/mnist,您将看到与您从容器外部发出 ls /home/jsmith/data/mnist 命令时相同的文件。

container_dir
您在容器内部时的目标目录。例如,/data/mnist 是示例中的目标目录
复制
已复制!
            

-v /home/jsmith/data/mnist:/data/mnist

<xx.xx>
容器版本。例如,24.05
py<x>
Python 版本。例如,py3

3.2. 访问和从 NGC 容器注册表中拉取

开始之前

按照 NGC 站点上的用户指南操作,以便能够访问 NGC 软件,包括获取 NGC API 密钥。确保您使用运行 Docker 容器所需的权限登录到客户端计算机。获得对 NGC 的访问权限后,您可以通过以下两种方式之一访问 NGC 容器注册表:

关于此任务

Docker 注册表是存储 Docker 镜像的服务。该服务可以在互联网上、公司内部网上或本地计算机上。例如,nvcr.io 是 Docker 镜像的 NGC 容器注册表的位置。

所有 nvcr.io Docker 镜像都使用显式的容器版本标签,以避免使用 latest 标签可能导致的标记问题。例如,本地标记为“latest”版本的镜像实际上可能会覆盖注册表中的不同“latest”版本。

步骤

  1. 登录到 NGC 容器注册表。
    复制
    已复制!
                

    $ docker login nvcr.io

  2. 当提示您输入用户名时,输入以下文本
    复制
    已复制!
                

    $oauthtoken

    $oauthtoken 用户名是一个特殊用户名,指示您将使用 API 密钥而不是用户名和密码进行身份验证。
  3. 当提示您输入密码时,输入您的 NGC API 密钥。
    复制
    已复制!
                

    Username: $oauthtoken Password: k7cqFTUvKKdiwGsPnWnyQFYGnlAlsCIRmlP67Qxa

    提示

    当您获得 API 密钥时,将其复制到剪贴板,以便在提示您输入密码时,可以将 API 密钥粘贴到命令 shell 中。此外,请务必将其存储在安全的地方,因为您以后可能需要它。

3.2.1. 使用 Docker CLI 从 NGC 容器注册表中拉取容器

开始之前

在拉取容器之前,请确保满足以下先决条件:

  • 您具有对包含容器的注册表空间的读取访问权限。
  • 您已登录到 NGC 容器注册表,如 访问和从 NGC 容器注册表中拉取 中所述,并且您已将 API 密钥存储在安全且可访问的位置。
  • 您的帐户是 docker 组的成员,这使您可以使用 Docker 命令。
提示

要浏览 NGC 容器注册表中可用的容器,请使用 Web 浏览器登录到 NGC 网站上的 NGC 容器注册表帐户。


步骤

  1. 从注册表中拉取您想要的容器。例如,要拉取 PyTorch™ 21.02 容器
    复制
    已复制!
                

    $ docker pull nvcr.io/nvidia/pytorch:21.02-py3

  2. 列出系统上的 Docker 镜像以确认已拉取容器。
    复制
    已复制!
                

    $ docker images

下一步做什么


拉取容器后,您可以在容器中运行作业以运行科学工作负载、训练神经网络、部署深度学习模型或执行 AI 分析。

3.2.2. 使用 NGC Web 界面拉取容器

开始之前

在您可以从 NGC 容器注册表中拉取容器之前,您必须已安装 Docker 和 nvidia-docker2,如 准备使用 NVIDIA 容器入门指南 中所述。您还必须具有对 NGC 容器注册表的访问权限并已登录,如 NGC 入门指南 中所述。

关于此任务

此任务假定:

  1. 您有一个云实例系统,并且已连接到互联网。
  2. 您的实例已安装 Docker 和 nvidia-docker2。
  3. 您可以访问 https://ngc.nvidia.com 上的 NGC 容器注册表的浏览器,并且您的 NGC 帐户已激活。
  4. 您想要将容器拉取到您的云实例上。

步骤

  1. 登录到 https://ngc.nvidia.com 上的 NGC 容器注册表。
  2. 单击左侧导航栏中的注册表。浏览 NGC 容器注册表页面以确定哪些 Docker 存储库和标签可供您使用。
  3. 单击其中一个存储库以查看有关该容器镜像的信息以及您在运行容器时将使用的可用标签。
  4. 拉取列中,单击图标以复制 Docker 拉取命令。
  5. 打开命令提示符并粘贴 Docker 拉取命令。容器镜像的拉取开始。确保拉取成功完成。
  6. 在本地系统上拥有 Docker 容器文件后,将容器加载到本地 Docker 注册表中。
  7. 验证镜像是否已加载到本地 Docker 注册表中。
    复制
    已复制!
                

    $ docker images

    有关与您的特定容器相关的更多信息,请参阅容器内的 /workspace/README.md 文件。

3.3. 验证

Docker 镜像运行后,您可以使用经典的 *nix 选项 ps 进行验证。例如,发出 $ docker ps -a 命令。

复制
已复制!
            

[username ~]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED 12a4854ba738 nvcr.io/nvidia/tensorflow:21.02 "/usr/local/bin/nv..." 35 seconds ago


如果没有 -a 选项,则仅列出正在运行的实例。

重要提示

最好包含 -a 选项,以防有挂起的作业正在运行或其他性能问题。


如果需要,您也可以停止正在运行的容器。例如

复制
已复制!
            

[username ~]$ docker ps -a CONTAINER ID IMAGE COMMAND PORTS NAMES 12a4854ba738 nvcr.io/nvidia/tensorflow:21.02 "/usr/local/bin/nv..." 6006/tcp brave_neumann [username ~]$ [username ~]$ docker stop 12a4854ba738 12a4854ba738 [username ~]$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED NAMES


请注意,您需要要停止的镜像的容器 ID。可以使用 $ docker ps -a 命令找到它。另一个有用的命令或 Docker 选项是从服务器中删除镜像。删除镜像可以节省服务器上的空间。例如,发出以下命令

复制
已复制!
            

$ docker rmi nvcr.io/nvidia.tensorflow:21.02


如果您列出服务器上的镜像,$ docker images,那么您将看到该镜像已不在那里。


NGC 容器托管在名为 nvcr.io 的存储库中。正如您在前一节中读到的那样,这些容器可以从存储库“拉取”出来,并用于 GPU 加速应用程序,例如科学工作负载、可视化和深度学习。

Docker 镜像只是开发人员构建的文件系统。每个层都依赖于堆栈中其下方的层。

从 Docker 镜像中,当 Docker 镜像被“运行”或实例化时,就会创建一个容器。创建容器时,您在堆栈顶部添加一个可写层。添加了可写容器层的 Docker 镜像就是一个容器。容器只是该镜像的运行实例。对容器所做的所有更改和修改都将应用于可写层。您可以删除容器;但是,Docker 镜像保持不变。图 1 描绘了 DGX 系列系统的堆栈。请注意,NVIDIA 容器工具包位于主机操作系统和 NVIDIA 驱动程序之上。这些工具用于创建、管理和使用 NVIDIA 容器 - 这些是 nvidia-docker 层之上的层。这些容器具有应用程序、深度学习 SDK 和 CUDA 工具包。NVIDIA 容器化工具负责挂载适当的 NVIDIA 驱动程序。

图 1. Docker 容器封装应用程序依赖项以提供可重现且可靠的执行。nvidia-docker 实用程序在启动时将 NVIDIA 驱动程序的用户模式组件和 GPU 挂载到 Docker 容器中。

software_stack_zoom.png

4.1. NGC 镜像版本

Docker 镜像的每个发布版本都由一个版本“标签”标识。对于较简单的镜像,此版本标签通常包含镜像中主要软件包的版本。对于包含多个软件包或版本的更复杂镜像,可能会使用一个单独的版本来专门表示容器化的软件配置。一种常见的方案是使用由镜像发布年份和月份定义的标签。例如,镜像的 21.02 版本是在 2021 年 2 月发布的。完整的镜像名称由两部分组成,中间用冒号分隔。第一部分是仓库中容器的名称,第二部分是与容器关联的“标签”。这些信息显示在图 2中,该图是发出 docker images 命令的输出。

图 2. docker images 命令的输出

image_versions.png

图 2 显示了镜像名称的简单示例,例如:

  • nvidia-cuda:8.0-devel
  • ubuntu:latest
  • nvcr.io/nvidia/tensorflow:21.01

如果您选择不向镜像添加标签,则默认情况下会添加单词“latest”作为标签,但是所有 NGC 容器都有显式的版本标签。

在接下来的章节中,您将使用这些镜像名称来运行容器。本文档的后面部分还将介绍创建您自己的容器或自定义和扩展现有容器。


开始之前

在您可以运行 NGC 深度学习框架容器之前,您的 Docker 环境必须支持 NVIDIA GPU。要运行容器,请按照本章中的说明发出相应的命令,指定注册表、仓库和标签。

5.1. 为 NGC 容器启用 GPU 支持

在具有 NGC 容器 GPU 支持的系统上,运行容器时会发生以下情况:

  • Docker 引擎将镜像加载到运行软件的容器中。
  • 您可以通过包含与命令一起使用的其他标志和设置来定义容器的运行时资源。以下各节将描述这些标志和设置。
  • GPU 显式地为 Docker 容器定义(默认为所有 GPU,可以使用 NV_GPU 环境变量指定)。

系统中实现的方法取决于已安装的 DGX OS 版本(对于 DGX 系统)、云服务提供商提供的特定 NGC 云镜像,或者您为在 TITAN PC、Quadro PC 或 vGPU 上运行 NGC 容器而准备安装的软件。请参阅下表以帮助确定系统中实现了哪种方法。

GPU 支持方法何时使用如何确定
原生 GPU 支持包含在 Docker-ce 19.03 或更高版本中运行 docker version 以确定已安装的版本。


每种方法都通过使用特定的 Docker 命令来调用,如下所述。

使用原生 GPU 支持

注意

如果在已安装 nvidia-dockernvidia-docker2 的系统上将 Docker 更新到 19.03,则仍然可以使用相应的方法。

  • 要在新安装的 Docker 上使用原生支持,请首先在 Docker 中启用新的 GPU 支持。
    复制
    已复制!
                

    $ sudo apt-get install -y docker nvidia-container-toolkit

    如果您已在安装了 nvidia-docker2 的系统上将 Docker 更新到 19.03,则无需执行此步骤。原生支持将自动启用。
  • 使用 docker run --gpus 运行启用 GPU 的容器。
    • 使用所有 GPU 的示例
      复制
      已复制!
                  

      $ docker run --gpus all ...

    • 使用两个 GPU 的示例
      复制
      已复制!
                  

      $ docker run --gpus 2 ...

    • 使用特定 GPU 的示例
      复制
      已复制!
                  

      $ docker run --gpus "device=1,2" ... $ docker run --gpus "device=UUID-ABCDEF,1" ...

示例:运行容器

步骤

  1. 作为用户,以交互方式运行容器。
    复制
    已复制!
                

    $ docker run --gpus all -it --rm –v local_dir:container_dir nvcr.io/nvidia/<repository>:<xx.xx>

    注意

    基本命令 docker run --gpu all 假定您的系统已安装 Docker 19.03-CE。有关早期版本 Docker 使用的命令,请参阅为 NGC 容器启用 GPU 支持部分。

    示例: 以下示例以交互模式运行 2021 年 2 月发布 (21.02) 的 NVIDIA PyTorch 容器。当用户退出容器时,容器会自动删除。
    复制
    已复制!
                

    $ docker run --gpus all --rm -ti nvcr.io/nvidia/pytorch:21.02-py3 ================== == NVIDIA PyTorch == ================== NVIDIA Release 21.02 (build 11032) Container image Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. Copyright (c) 2014 - 2019, The Regents of the University of California (Regents) All rights reserved. Various files include modifications (c) NVIDIA CORPORATION. All rights reserved. NVIDIA modifications are covered by the license terms that apply to the underlying project or file. root@df57eb8e0100:/workspace#

  2. 在容器内,启动您要运行的作业。要运行的精确命令取决于您正在运行的容器中的深度学习框架以及您要运行的作业。有关详细信息,请参阅容器的 /workspace/README.md 文件。示例: 以下示例在一个 GPU 上运行 pytorch time 命令,以测量 deploy.prototxt 模型的执行时间。
    复制
    已复制!
                

    # pytorch time -model models/bvlc_alexnet/ -solver deploy.prototxt -gpu=0

  3. 可选: 运行相同 NVIDIA PyTorch 容器的 2021 年 2 月发布 (21.02) 版本,但在非交互模式下运行。
    复制
    已复制!
                

    % docker run --gpus all -it --rm -v local_dir:container_dir nvcr.io/nvidia/pytorch:<xx.xx>-py3 <command>

5.3. 指定用户

除非另有说明,否则容器内的用户是 root 用户。在容器内运行时,主机操作系统或网络卷上创建的文件可以由 root 用户访问。这对于某些用户来说是不可接受的,他们希望在容器中设置用户的 ID。例如,要将容器中的用户设置为当前正在运行的用户,请发出以下命令

复制
已复制!
            

% docker run --gpus all -ti --rm -u $(id -u):$(id -g) nvcr.io/nvidia/<repository>:<container version>


通常,这会导致警告,因为指定的用户名和组在容器中不存在。您可能会看到类似于以下内容的消息

复制
已复制!
            

groups: cannot find name for group ID 1000I have no name! @c177b61e5a93:/workspace$

通常可以忽略此警告。

5.4. 设置删除标志


默认情况下,Docker 容器在运行后仍保留在系统上。重复的 pull 或 run 操作会占用本地磁盘上越来越多的空间,即使在退出容器后也是如此。因此,在退出后清理容器非常重要。

注意

如果您对容器进行了要保存的更改,或者您想在运行完成后访问作业日志,请不要使用 --rm 标志。


要退出时自动删除容器,请将 --rm 标志添加到 run 命令。

复制
已复制!
            

% docker run --gpus all --rm nvcr.io/nvidia/<repository>:<container version>

5.5. 设置交互标志

默认情况下,容器以批处理模式运行;也就是说,容器运行一次然后退出,无需任何用户交互。容器也可以作为服务以交互模式运行。要以交互模式运行,请将 -ti 标志添加到 run 命令。

复制
已复制!
            

% docker run --gpus all -ti --rm nvcr.io/nvidia/<repository>:<container version>

5.6. 设置卷标志

容器中不包含数据集,因此,如果您想使用数据集,则需要从主机操作系统将卷挂载到容器中。有关更多信息,请参阅管理容器中的数据

通常,您将使用 Docker 卷或主机数据卷。主机数据卷和 Docker 卷之间的主要区别在于 Docker 卷是 Docker 私有的,只能在 Docker 容器之间共享。Docker 卷在主机操作系统中不可见,Docker 管理数据存储。主机数据卷是主机操作系统中可用的任何目录。这可以是您的本地磁盘或网络卷。

示例 1
将主机操作系统上的目录 /raid/imagedata 挂载为容器中的 /images
复制
已复制!
            

% docker run --gpus all -ti --rm -v /raid/imagedata:/images nvcr.io/nvidia/<repository>:<container version>

示例 2
将名为 data 的本地 docker 卷(如果尚不存在,则必须创建)挂载为容器中的 /imagedata
复制
已复制!
            

% docker run --gpus all -ti --rm -v data:/imagedata nvcr.io/nvidia/<repository>:<container version>

5.7. 设置端口映射标志

深度学习 GPU 训练系统™ (DIGITS) 等应用程序会打开一个端口进行通信。您可以控制该端口仅在本地系统上打开,还是可供本地系统外部网络上的其他计算机使用。以 DIGITS 为例,在容器镜像 16.12 中开始的 DIGITS 5.0 中,默认情况下,DIGITS 服务器在端口 5000 上打开。但是,在容器启动后,您可能不容易知道该容器的 IP 地址。要了解容器的 IP 地址,您可以选择以下方法之一:

  • 使用本地系统网络堆栈 (--net=host) 公开端口,其中容器的端口 5000 可用作本地系统的端口 5000。

  • 映射端口 (-p 8080:5000),其中容器的端口 5000 可用作本地系统的端口 8080。

在任何一种情况下,本地系统外部的用户都看不到 DIGITS 正在容器中运行。如果不发布端口,则该端口仍然可以从主机访问,但不能从外部访问。

5.8. 设置共享内存标志

某些应用程序(例如 PyTorch™)使用共享内存缓冲区在进程之间进行通信。单个进程应用程序(例如 NVIDIA 优化的深度学习框架,由 Apache MXNet™ 和 TensorFlow™ 提供支持)也可能需要共享内存,这些应用程序使用 NVIDIA® 集体通信库™ (NCCL)。

默认情况下,Docker 容器分配 64MB 的共享内存。这可能不足,尤其是在使用所有 8 个 GPU 时。要将共享内存限制增加到指定大小(例如 1GB),请在 docker run 命令中包含 --shm-size=1g 标志。

或者,您可以指定 --ipc=host 标志以在容器内重用主机的共享内存空间。尽管后一种方法具有安全隐患,因为共享内存缓冲区中的任何数据都可能对其他容器可见。

5.9. 设置限制 GPU 暴露的标志

从容器内部,脚本和软件被编写为利用所有可用的 GPU。为了在更高级别协调 GPU 的使用,您可以使用此标志来限制从主机到容器的 GPU 暴露。例如,如果您只想在容器中看到 GPU 0 和 GPU 1,您将发出以下命令:

使用原生 GPU 支持

$ docker run --gpus"device=0,1" ...

使用 nvidia-docker2

$ NV_GPU=0,1 docker run --runtime=nvidia ...

使用 nvidia-docker

$ NV_GPU=0,1 nvidia-docker run ...

此标志创建一个临时环境变量,用于限制使用哪些 GPU。

指定的 GPU 是通过 Docker 设备映射功能为每个容器定义的,该功能目前基于 Linux cgroups

5.10. 容器生命周期

如果您不将 --rm 标志传递给 docker run --gpus 命令,则退出的容器的状态将无限期地保留。您可以使用以下命令列出所有已保存的已退出容器及其在磁盘上的大小

复制
已复制!
            

$ docker ps --all --size --filter Status=exited


容器在磁盘上的大小取决于容器执行期间创建的文件,因此退出的容器仅占用少量磁盘空间。您可以通过发出以下命令永久删除退出的容器

复制
已复制!
            

docker rm [CONTAINER ID]


通过保存容器退出后的状态,您仍然可以使用标准 Docker 命令与其进行交互。例如:

  • 您可以使用 docker logs 命令检查过去执行的日志。
    复制
    已复制!
                

    $ docker logs 9489d47a054e

  • 您可以使用 docker cp 命令提取文件。
    复制
    已复制!
                

    $ docker cp 9489d47a054e:/log.txt .

  • 您可以使用 docker restart 命令重新启动已停止的容器。
    复制
    已复制!
                

    $ docker restart <container name>

    对于 PyTorch 容器,发出此命令
    复制
    已复制!
                

    $ docker restart pytorch

  • 您可以使用 docker commit 命令通过创建新镜像来保存您的更改。有关更多信息,请参阅 示例 3:使用 docker commit 自定义容器。
    注意

    提交 Docker 容器更改时请务必小心,因为在使用容器期间创建的数据文件将添加到结果镜像中。特别是,核心转储文件和日志会显着增加结果镜像的大小。


NVIDIA 深度学习软件开发工具包 (SDK) 包含 NVIDIA 注册表区域中用于 DGX 系统的所有内容;包括 CUDA 工具包、DIGITS 和所有深度学习框架。NVIDIA 深度学习 SDK 加速了广泛使用的深度学习框架,例如 NVIDIA 优化的深度学习框架、由 Apache MXNet、PyTorch 和 TensorFlow 提供支持的框架。

注意

从 18.09 容器版本开始,Caffe2、Microsoft Cognitive Toolkit、Theano™ 和 Torch™ 框架不再在容器镜像中提供。


该软件堆栈提供针对系统优化的这些框架的容器化版本。这些框架(包括所有必要的依赖项)都已预构建、测试、调整和准备运行。对于需要更大灵活性来构建自定义深度学习解决方案的用户,每个框架容器镜像还包括框架源代码,以支持自定义修改和增强,以及完整的软件开发堆栈。

平台软件的设计围绕服务器上安装的最小操作系统和驱动程序,以及通过 DGX 系统的 NGC 容器注册表在容器中配置所有应用程序和 SDK 软件。

所有 NGC 容器镜像都基于平台层 (nvcr.io/nvidia/cuda)。此镜像提供了所有其他 NGC 容器的基础软件开发堆栈的容器化版本,并且可供需要更大灵活性以构建具有自定义应用程序的容器的用户使用。

6.1. 操作系统层

在软件堆栈中,最底层(或基础层)是操作系统的用户空间。此层中的软件包括发布月份内可用的所有安全补丁。

6.2. CUDA 层

CUDA® 是 NVIDIA 创建的并行计算平台和编程模型,旨在让应用程序开发人员能够访问 GPU 的大规模并行处理能力。CUDA 是 GPU 加速深度学习的基础,也是从天文学到分子动力学模拟,再到计算金融等各种其他计算和内存密集型应用程序的基础。有关 CUDA 的更多信息,请参阅CUDA 文档

6.2.1. CUDA 运行时

CUDA 运行时层提供了在部署环境中执行 CUDA 应用程序所需的组件。CUDA 运行时与 CUDA 工具包一起打包,包括所有共享库,但不包括任何 CUDA 编译器组件。

6.2.2. CUDA 工具包

CUDA 工具包为开发优化的 GPU 加速应用程序提供了开发环境。借助 CUDA 工具包,您可以开发、优化应用程序并将其部署到 GPU 加速的嵌入式系统、桌面工作站、企业数据中心和云。CUDA 工具包包括库、用于调试和优化的工具、编译器和用于部署应用程序的运行时库。以下库为深度神经网络提供 GPU 加速的原语

CUDA® 基本线性代数子程序库™ (cuBLAS) (cuBLAS)
cuBLAS 是完整标准 BLAS 库的 GPU 加速版本,可在 GPU 上运行时提供显着的加速。cuBLAS 通用矩阵-矩阵乘法 (GEMM) 例程是深度神经网络中使用的关键计算,例如在计算全连接层时。有关 cuBLAS 的更多信息,请参阅cuBLAS 文档

6.3. 深度学习库层

以下库对于 NVIDIA GPU 上的深度学习至关重要。这些库是 NVIDIA 深度学习软件开发工具包 (SDK) 的一部分。

6.3.1. NCCL

NVIDIA® 集体通信库™ (NCCL)(NCCL,发音为“Nickel”)是一个多 GPU 集体通信原语库,它感知拓扑结构,并且可以轻松集成到应用程序中。集体通信算法采用多个处理器协同工作来聚合数据。NCCL 不是一个成熟的并行编程框架;相反,它是一个专注于加速集体通信原语的库。当前支持以下集体操作:

  • AllReduce
  • Broadcast
  • Reduce
  • AllGather
  • ReduceScatter

通信处理器之间的紧密同步是集体通信的关键方面。传统的基于 CUDA 的集体通信将通过 CUDA 内存复制操作和 CUDA 内核的组合来实现本地缩减。另一方面,NCCL 在单个内核中实现每个集体通信,处理通信和计算操作。这样可以实现快速同步,并最大限度地减少达到峰值带宽所需的资源。

NCCL 方便地消除了开发人员针对特定机器优化其应用程序的需求。NCCL 在多个 GPU 之间以及跨节点提供快速的集体通信。它支持各种互连技术,包括 PCIe、NVLink™、InfiniBand Verbs 和 IP 套接字。NCCL 还会自动调整其通信策略以匹配系统的底层 GPU 互连拓扑。除了性能之外,编程的简易性也是 NCCL 设计中的主要考虑因素。NCCL 使用简单的 C API,可以从各种编程语言轻松访问。NCCL 紧密遵循 MPI(消息传递接口)定义的流行的集体通信 API。因此,任何熟悉 MPI 的人都会发现 NCCL 的 API 非常自然易用。与 MPI 的一个细微不同之处在于,NCCL 集体通信采用“流”参数,该参数提供了与 CUDA 编程模型的直接集成。最后,NCCL 与几乎任何多 GPU 并行化模型兼容,例如:

  • 单线程
  • 多线程,例如,每个 GPU 使用一个线程
  • 多进程,例如,MPI 与 GPU 上的多线程操作相结合

NCCL 在深度学习框架中找到了广泛的应用,其中 AllReduce 集体通信被大量用于神经网络训练。借助 NCCL 提供的多 GPU 和多节点通信,可以实现神经网络训练的有效扩展。

有关 NCCL 的更多信息,请参阅NCCL 文档

6.3.2. cuDNN 层

CUDA® 深度神经网络库™ (cuDNN) (cuDNN) 为标准例程(例如前向和后向卷积、池化、归一化和激活层)提供了高度优化的实现。

框架的进展速度并不完全相同,并且 cuDNN 库中缺少向后兼容性,这迫使它位于自己的容器中。这意味着将有多个 CUDA 和 cuDNN 容器可用,但它们都将有自己的标签,框架需要在其 Dockerfile 中指定该标签。

有关 cuDNN 的更多信息,请参阅cuDNN 文档

6.4. 框架容器

框架层包括特定深度学习框架的所有要求。此层的主要目标是提供基本的工作框架。可以通过平台容器层规范进一步自定义框架。在框架层中,您可以选择:

  • 完全按照 NVIDIA 交付的方式运行框架;在这种情况下,框架已构建并准备好在该容器镜像内运行。
  • 从 NVIDIA 交付的框架开始并对其进行少量修改;在这种情况下,您可以从 NVIDIA 的容器镜像开始,应用您的修改并在容器内重新编译它。
  • 从头开始,并在 NVIDIA 提供的 CUDA 和 cuDNN 以及 NCCL 层之上构建您想要的任何应用程序。

在下一节中,将介绍 NVIDIA 深度学习框架容器。

有关框架的更多信息,请参阅框架文档


深度学习框架是软件堆栈的一部分,该堆栈由多个层组成。每一层都依赖于堆栈中其下方的层。此软件架构具有许多优点:

  • 由于每个深度学习框架都位于单独的容器中,因此每个框架可以使用不同版本的库,例如称为 libc、cuDNN 和其他库的 C 标准库,而不会相互干扰。
  • 拥有分层容器的一个关键原因是,可以针对用户需求来定制体验。
  • 随着深度学习框架在性能或错误修复方面得到改进,注册表中会提供新版本的容器。
  • 系统易于维护,并且操作系统镜像保持清洁,因为应用程序不是直接安装在操作系统上的。
  • 可以无缝交付安全更新、驱动程序更新和操作系统补丁。

以下各节介绍了 nvcr.io 中的框架容器。

7.1. 为什么要使用深度学习软件框架?

创建框架是为了使深度学习的研究和应用更易于访问和高效。使用框架的主要好处包括:

  • 框架提供高度优化的 GPU 启用代码,专门用于训练深度神经网络 (DNN) 所需的计算。
  • NVIDIA 框架经过调整和测试,可实现最佳 GPU 性能。
  • 框架通过简单的命令行或脚本语言接口(例如 Python)提供对代码的访问。
  • 可以使用这些框架训练和部署许多强大的 DNN,而无需编写任何 GPU 或复杂的编译代码,但仍然可以从 GPU 加速带来的训练速度提升中受益。

7.2. Kaldi

Kaldi 语音识别工具包项目于 2009 年在约翰·霍普金斯大学启动,旨在开发降低构建语音识别系统所需的成本和时间的技术。虽然最初专注于为新语言和领域提供 ASR 支持,但 Kaldi 项目的规模和功能稳步增长,使数百名研究人员能够参与推动该领域的发展。现在,作为社区中事实上的语音识别工具包,Kaldi 帮助实现了每天被数百万人使用的语音服务。

有关已对 Kaldi 进行的优化和更改的信息,请参阅深度学习框架 Kaldi 发行说明

7.3. TensorFlow

TensorFlow™ 是一个开源软件库,用于使用数据流图进行数值计算。图中的节点表示数学运算,而图的边表示在它们之间流动的多维数据数组(张量)。这种灵活的架构使您可以将计算部署到桌面、服务器或移动设备中的一个或多个 CPU 或 GPU,而无需重写代码。

TensorFlow 最初由 Google 机器智能研究组织内 Google Brain 团队的研究人员和工程师开发,目的是进行机器学习和深度神经网络研究。该系统具有足够的通用性,也适用于各种其他领域。

为了可视化 TensorFlow 结果,此特定的 Docker 镜像还包含 TensorBoard。TensorBoard 是一套可视化工具。例如,您可以查看训练历史记录以及模型的结构。

有关已对 TensorFlow 进行的优化和更改的信息,请参阅深度学习框架发行说明

运行 TensorFlow 容器

在 GPU 系统上高效运行 TensorFlow 的一种有效方法是设置一个启动器脚本,以使用 TensorFlow Docker 容器运行代码。有关如何在系统上使用多个 GPU 运行 CIFAR-10 的示例,使用 cifar10_multi_gpu_train.py,请参阅 TensorFlow 模型。如果您更喜欢使用脚本来运行 TensorFlow,请参阅 run_tf_cifar10.sh 部分中的 run_tf_cifar10.sh 脚本。这是一个 bash 脚本,您可以在系统上运行它。它假定您已将 Docker 容器从 nvcr.io 仓库拉取到系统。它还假定您已将 CIFAR-10 数据存储在系统上的 /datasets/cifar 中,并将其映射到容器中的 /datasets/cifar。您还可以将参数传递给脚本,例如以下参数

复制
已复制!
            

$./run_tf_cifar10.sh --data_dir=/datasets/cifar --num_gpus=8


run_tf_cifar10.sh 脚本参数化的详细信息在本文档的 Keras 部分中进行了解释(请参阅)。您可以修改脚本中的 /datasets/cifar 路径,以使其指向特定站点的 CIFAR 数据位置。如果 TensorFlow 的 CIFAR-10 数据集不可用,则使用可写卷 -v /datasets/cifar:/datasets/cifar (不带 ro)运行示例,数据将在首次运行时下载。

如果您想并行化 CIFAR-10 训练,也可以通过 Keras 完成 TensorFlow 的基本数据并行化。请参阅 GitHub 上的示例 cifar10_cnn_mgpu.py

有关使用 Docker 容器编排 Python 脚本的描述,请参见 run_tf_cifar10.sh 脚本。

7.4. PyTorch

PyTorch 是一个 GPU 加速的张量计算框架,带有 Python 前端。PyTorch 旨在与 Python 深度集成。您可以像使用 NumPySciPyscikit-learn 或任何其他 Python 扩展一样自然地使用它。您甚至可以使用诸如 CythonNumba 之类的库在 Python 中编写神经网络层。包括 NVIDIA 的 cuDNNNCCL 以及 Intel 的 MKL 等加速库,以最大限度地提高性能。

PyTorch 还包括标准定义的神经网络层、深度学习优化器、数据加载实用程序以及多 GPU 和多节点支持。函数会立即执行,而不是在静态图中排队,从而提高了易用性和完善的调试体验。

有关已对 PyTorch 进行的优化和更改的信息,请参阅深度学习框架 PyTorch 发行说明


作为 DGX 系统的一部分,NVIDIA 为主要的深度学习框架提供了经过调整、优化、测试和准备运行的 Docker 容器。这些容器通过 NGC 容器注册表 nvcr.io 提供,以便您可以直接使用它们,或将它们用作创建您自己的容器的基础。

本文节介绍有效使用这些框架的技巧。有关如何使用 Docker 的最佳实践,请参阅Docker 和容器最佳实践。要开始使用 NVIDIA 容器,请参阅准备使用 NVIDIA 容器

8.1. 扩展容器

关于 nvcr.io 中的容器(框架),有一些通用的最佳实践。如前所述,可以使用其中一个容器并在此基础上进行构建(扩展)。通过这样做,在某种意义上,您是将新容器固定到特定的框架和容器版本。如果您要创建框架的衍生版本或添加框架或容器中不存在的某些功能,则此方法效果良好。

但是,如果您扩展框架,请理解在几个月后,框架很可能已经发生了变化。这是由于深度学习和深度学习框架的快速发展所致。通过扩展特定的框架,您已将扩展锁定到该特定版本的框架中。随着框架的发展,您将不得不将您的扩展添加到这些新版本中,从而增加您的工作量。如果可能,强烈建议不要将扩展绑定到特定的容器,而是将它们放在外部。如果扩展具有侵入性,则建议与框架团队讨论补丁的包含问题。

8.2. 数据集和容器

您可能会试图通过将数据集放入容器中来扩展容器。但是,您再次将该容器固定到特定版本。如果您转到新版本的框架或新框架,则必须将数据复制到其中。这使得跟上框架的快速发展变得非常困难。

最佳实践是不将数据集放入容器中。如果可能,还要避免将业务逻辑代码存储在容器中。原因在于,通过在容器中存储数据集或业务逻辑代码,很难概括容器的用法。

相反,可以将文件系统挂载到容器中,其中仅包含所需的数据集和包含要运行的业务逻辑代码的目录。将容器与特定数据集和业务逻辑解耦使您可以轻松更改容器(例如框架或容器版本),而无需重建容器来保存数据或代码。

后续章节简要介绍了关于容器注册表 (nvcr.io) 中容器内主要框架的一些最佳实践。还有一个章节讨论了如何将 Keras(深度学习框架的一个非常流行的高级抽象)与某些容器一起使用。

8.3. 使用容器化的 VNC 桌面环境

对容器化桌面的需求因数据中心设置而异。如果系统设置在登录节点或本地系统的主节点之后,通常数据中心将提供 VNC 登录节点或在登录节点上运行 X Windows,以方便运行文本编辑器或 IDE(集成开发环境)等可视化工具。

对于基于云的系统 (NGC),可能已经存在防火墙和安全规则。在这种情况下,您可能需要确保为 VNC 或类似工具打开了正确的端口。

如果系统既充当开发和计算的主要资源,则可以通过容器化桌面在其上设置类似桌面的环境。有关此操作的说明和 Dockerfile 可以在此处找到。您可以将最新版本的容器下载到系统。下一步是通过更改 FROM 字段来修改 Dockerfile,使其变为

复制
已复制!
            

FROM nvcr.io/nvidia/cuda:11.0-cudnn6-devel-ubuntu20.04


这不是 NVIDIA DGX 产品团队官方支持的容器,换句话说,它在 nvcr.io 上不可用,仅作为如何在系统上设置类似桌面的环境以方便使用 eclipsesublime-text(建议尝试 Visual Studio Code,它非常像 Sublime Text,但免费)或任何其他 GUI 驱动工具进行开发的示例。

build_run_dgxdesk.sh 示例脚本可在 GitHub 站点上找到,用于构建和运行容器化桌面,如脚本部分所示。DGX Station 和 NGC 等其他系统将遵循类似的过程。要连接到系统,您可以从 RealVnc 下载适用于您系统的 VNC 客户端,或使用 Web 浏览器。

复制
已复制!
            

=> connect via VNC viewer hostip:5901, default password: vncpassword

复制
已复制!
            

=> connect via noVNC HTML5 client: http://hostip:6901/?password=vncpassword


HPC 可视化容器

除了访问NVIDIA 优化的框架和 HPC 容器外,NGC 容器注册表还托管用于 HPC 的科学可视化容器。这些容器依赖于流行的科学可视化工具 ParaView。HPC 环境中的可视化通常需要远程可视化,即数据驻留在远程 HPC 系统或云中并在其上进行处理,用户通过工作站以图形方式与此应用程序进行交互。由于某些可视化容器需要专门的客户端应用程序,因此 HPC 可视化容器由两个组件组成

服务器容器
服务器容器需要访问服务器系统上的文件。下面提供了有关如何授予此访问权限的详细信息。服务器容器可以以串行模式或并行模式运行。对于此 Alpha 版本,我们专注于串行节点配置。如果您对并行配置感兴趣,请联系 hpcviscontainer@nvidia.com
客户端容器
为确保客户端应用程序和服务器容器的版本匹配,NVIDIA 在容器中提供了客户端应用程序。与服务器容器类似,客户端容器也需要访问某些端口才能与服务器容器建立连接。

此外,客户端容器需要访问用户的 X 服务器才能显示图形用户界面。

NVIDIA 建议将主机文件系统映射到客户端容器中,以便能够保存可视化产品或其他数据。此外,需要打开客户端和服务器容器之间的连接。

有关可用 HPC 可视化容器的列表以及如何使用它们的步骤,请参阅NGC 容器用户指南


NVIDIA Docker 镜像经过预先打包、调整和准备就绪,可以立即运行;但是,您可能希望从头开始构建新镜像,或使用自定义代码、库、数据或设置来增强现有镜像以适应您的企业基础架构。本节将指导您完成一些练习,这些练习将重点介绍如何从头开始创建容器、定制容器、扩展深度学习框架以添加功能、从开发人员环境中使用扩展框架开发一些代码,然后将该代码打包为版本化版本。

默认情况下,您不需要构建容器。NGC 容器注册表 nvcr.io 有许多可以立即使用的容器。其中包括用于深度学习、科学计算和可视化的容器,以及仅包含 CUDA 工具包的容器。

容器的优点之一是它们可以用作创建新容器的起点。这可以称为“定制”或“扩展”容器。您可以完全从头开始创建容器,但是,由于这些容器很可能在 GPU 系统上运行,因此建议您至少从包含操作系统和 CUDA 的 nvcr.io 容器开始。但是,您不限于此,并且可以创建在系统中 CPU 上运行的容器,该容器不使用 GPU。在这种情况下,您可以从 Docker 的裸操作系统容器开始。但是,为了使开发更容易,您仍然可以从带有 CUDA 的容器开始 - 只是在使用容器时不使用它。

对于 DGX 系统,您可以将修改/扩展的容器推送到或保存到 NGC 容器注册表 nvcr.io。它们也可以与 DGX 系统的其他用户共享,但这需要一些管理员的帮助。重要的是要注意,所有深度学习框架镜像都包含构建框架本身以及所有先决条件的源代码。

注意

请勿在 Docker 构建时将 NVIDIA 驱动程序安装到 Docker 镜像中。

10.1. 定制容器

NVIDIA 在 NGC 容器注册表中提供了大量镜像,这些镜像已经过测试、调整并准备好运行。您可以拉取这些镜像中的任何一个来创建容器,并添加您选择的软件或数据。

最佳实践是避免使用 docker commit 来开发新的 Docker 镜像,而应使用 Dockerfile。Dockerfile 方法提供了在 Docker 镜像开发期间对所做更改进行版本控制的可视性和能力。docker commit 方法仅适用于短期的、一次性镜像(有关示例,请参阅示例 3:使用 docker commit 定制容器)。

有关编写 Docker 文件的更多信息,请参阅最佳实践文档

10.1.1. 定制容器的优点和局限性

您可以出于多种原因定制容器以满足您的特定需求;例如,您依赖于 NVIDIA 提供的容器中未包含的特定软件。无论您的原因是什么,您都可以定制容器。

除非容器镜像中包含框架源代码,否则它们不包含示例数据集或示例模型定义。请务必检查容器中是否有示例数据集或模型。

10.1.2. 示例 1:从头开始构建容器

关于此任务

Docker 使用 Dockerfile 来创建或构建 Docker 镜像。Dockerfile 是包含 Docker 依次用于创建新 Docker 镜像的命令的脚本。简而言之,Dockerfile 是容器镜像的源代码。Dockerfile 始终以基础镜像开头以从中继承,即使您仅使用基础操作系统也是如此。

有关编写 Dockerfile 的最佳实践,请参阅编写 Dockerfile 的最佳实践

作为示例,让我们从 Dockerfile 创建一个容器,该容器使用 Ubuntu 20.04 作为基础操作系统。创建容器时,我们还更新操作系统。

步骤

  1. 在本地硬盘驱动器上创建一个工作目录。
  2. 在该目录中,打开文本编辑器并创建一个名为 Dockerfile 的文件。将文件保存到您的工作目录。
  3. 打开您的 Dockerfile 并包含以下内容
    复制
    已复制!
                

    FROM ubuntu:20.04 RUN apt-get update && apt-get install -y curl CMD echo "hello from inside a container"

    最后一行 CMD 在创建容器时执行指示的命令。这是一种检查容器是否正确构建的方法。

    在此示例中,我们还从 Docker 存储库而不是 NGC 存储库中拉取容器。后续示例将使用 NVIDIA® 存储库。

  4. 保存并关闭您的 Dockerfile
  5. 构建镜像。发出以下命令以构建镜像并创建标签。
    复制
    已复制!
                

    $ docker build -t <new_image_name>:<new_tag> .

    注意

    此命令在 Dockerfile 所在的同一目录中发出。

    docker build 过程的输出列出了“步骤”;Dockerfile 中的每一行对应一个步骤。例如,让我们将容器命名为 test1 并使用 latest 标记它。此外,出于说明目的,让我们假设我们的私有 DGX 系统存储库名为 nvidian_sas(确切名称取决于您注册 DGX 的方式。这通常是某种形式的公司名称。)以下命令构建容器。下面显示了一些输出,以便您了解预期结果。

    复制
    已复制!
                

    $ docker build -t test1:latest . Sending build context to Docker daemon 8.012 kB Step 1/3 : FROM ubuntu:20.04 14.04: Pulling from library/ubuntu ... Step 2/3 : RUN apt-get update &amp;&amp; apt-get install -y curl ... Step 3/3 : CMD echo "hello from inside a container" ---> Running in 1f391b9285d8 ---> 934785072daf Removing intermediate container 1f391b9285d8 Successfully built 934785072daf


    有关构建镜像的信息,请参阅docker build。有关标记镜像的信息,请参阅docker tag

  6. 验证构建是否成功。您应该看到类似于以下内容的消息
    复制
    已复制!
                

    Successfully built 934785072daf

    此消息表明构建成功。任何其他消息都表明构建不成功。
    注意

    数字 934785072daf 在构建镜像时分配,并且是随机的。

  7. 确认您可以查看您的镜像。发出以下命令以查看您的容器。
    复制
    已复制!
                

    $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE test1 latest 934785072daf 19 minutes ago 222 MB

    新容器现在可以使用了。
    注意

    该容器是此 DGX 系统的本地容器。如果您想将容器存储在您的私有存储库中,请按照下一步操作。

    注意

    您需要拥有 DGX 系统才能执行此操作。

  8. 通过推送将容器存储在您的私有 Docker 存储库中。
    1. 推送它的第一步是标记它。
      复制
      已复制!
                  

      $ docker tag test1 nvcr.io/nvidian_sas/test1:latest

    2. 现在镜像已被标记,您可以将其推送到例如 nvcr.io 上名为 nvidian_sas 的私有项目中。
      复制
      已复制!
                  

      $ docker push nvcr.io/nvidian_sas/test1:latest The push refers to a repository [nvcr.io/nvidian_sas/test1] …

    3. 验证容器是否出现在 nvidian_sas 存储库中。

10.1.3. 示例 2:使用 Dockerfile 定制容器

关于此任务

此示例使用 Dockerfile 定制 nvcr.io 中的 PyTorch 容器。在定制容器之前,您应确保已使用 docker pull 命令将 PyTorch 21.02 容器加载到注册表中,然后再继续。

复制
已复制!
            

$ docker pull nvcr.io/nvidia/pytorch:21.02-py3


如本文档前面所述,nvcr.io 上的 Docker 容器还提供了一个示例 Dockerfile,其中说明了如何修补框架并重建 Docker 镜像。在目录 /workspace/docker-examples 中,有两个示例 Dockerfile。对于此示例,我们将使用 Dockerfile.customcaffe 文件作为定制容器的模板。

步骤

  1. 在本地硬盘驱动器上创建一个名为 my_docker_images 的工作目录。
  2. 打开文本编辑器并创建一个名为 Dockerfile 的文件。将文件保存到您的工作目录。
  3. 再次打开您的 Dockerfile,并在文件中包含以下行
    复制
    已复制!
                

    FROM nvcr.io/nvidia/pytorch:21.02 # APPLY CUSTOMER PATCHES TO PYTORCH # Bring in changes from outside container to /tmp # (assumes my-pytorch-modifications.patch is in same directory as Dockerfile) #COPY my-pytorch-modifications.patch /tmp # Change working directory to PyTorch source path WORKDIR /opt/pytorch # Apply modifications #RUN patch -p1 < /tmp/my-pytorch-modifications.patch # Note that the default workspace for caffe is /workspace RUN mkdir build && cd build && \ cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr/local -DUSE_NCCL=ON -DUSE_CUDNN=ON -DCUDA_ARCH_NAME=Manual -DCUDA_ARCH_BIN="35 52 60 61" -DCUDA_ARCH_PTX="61" .. && \ make -j"$(nproc)" install && \ make clean && \ cd .. && rm -rf build # Reset default working directory WORKDIR /workspace

    保存文件。
  4. 使用 docker build 命令构建镜像,并指定存储库名称和标签。在以下示例中,存储库名称为 corp/pytorch,标签为 21.02.1PlusChanges 。对于这种情况,命令将是以下内容
    复制
    已复制!
                

    $ docker build -t corp/pytorch:21.02.1PlusChanges .

  5. 运行 Docker 镜像。
    复制
    已复制!
                

    docker run --gpus all -ti --rm corp/pytorch:21.02.1PlusChanges .

10.1.4. 示例 3:使用 docker commit 定制容器

关于此任务


此示例使用 docker commit 命令将容器的当前状态刷新到 Docker 镜像。这不是推荐的最佳实践,但是,当您有一个正在运行的容器,您对其进行了更改并想要保存它们时,这非常有用。在此示例中,我们使用 apt-get 标记来安装软件包,这要求用户以 root 身份运行。

注意
  • NVCaffe 镜像版本 17.04 在示例说明中用于说明目的。
  • 运行容器时,请勿使用 --rm 标志。如果在运行容器时使用 --rm 标志,则退出容器时您的更改将丢失。

步骤

  1. nvcr.io 存储库中拉取 Docker 容器到 DGX 系统。例如,以下命令将拉取 NVCaffe 容器
    复制
    已复制!
                

    $ docker pull nvcr.io/nvidia/caffe:17.04

  2. 在 DGX 系统上运行容器。
    复制
    已复制!
                

    docker run --gpus all -ti nvcr.io/nvidia/caffe:17.04

    复制
    已复制!
                

    ================== == NVIDIA Caffe == ================== NVIDIA Release 17.04 (build 26740) Container image Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. Copyright (c) 2014, 2015, The Regents of the University of California (Regents) All rights reserved. Various files include modifications (c) NVIDIA CORPORATION. All rights reserved. NVIDIA modifications are covered by the license terms that apply to the underlying project or file. NOTE: The SHMEM allocation limit is set to the default of 64MB. This may be insufficient for NVIDIA Caffe. NVIDIA recommends the use of the following flags: docker run --gpus all --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 ... root@1fe228556a97:/workspace#

  3. 您现在应该是容器中的 root 用户(注意提示符)。您可以使用 apt 命令来拉取软件包并将其放入容器中。
    注意

    NVIDIA 容器是使用 Ubuntu 构建的,Ubuntu 使用 apt-get 软件包管理器。查看容器发行说明 深度学习文档,了解有关您正在使用的特定容器的详细信息。

    在此示例中,我们将把 Octave(MATLAB 的 GNU 克隆)安装到容器中。
    复制
    已复制!
                

    # apt-get update # apt install octave

    注意

    您必须先发出 apt-get update,然后才能使用 apt 安装 Octave。

  4. 退出工作区。
    复制
    已复制!
                

    # exit

  5. 使用 docker ps -a 显示容器列表。例如,这是 docker ps -a 命令的输出片段
    复制
    已复制!
                

    $ docker ps -a CONTAINER ID IMAGE CREATED ... 1fe228556a97 nvcr.io/nvidia/caffe:17.04 3 minutes ago ...

  6. 现在,您可以从正在运行的容器中创建一个新镜像,您已在其中安装了 Octave。您可以使用以下命令提交容器。
    复制
    已复制!
                

    $ docker commit 1fe228556a97 nvcr.io/nvidian_sas/caffe_octave:17.04 sha256:0248470f46e22af7e6cd90b65fdee6b4c6362d08779a0bc84f45de53a6ce9294

  7. 显示镜像列表。
    复制
    已复制!
                

    $ docker images REPOSITORY TAG IMAGE ID ... nvidian_sas/caffe_octave 17.04 75211f8ec225 ...

  8. 为了验证,让我们再次运行容器,看看 Octave 是否真的在那里。
    注意

    这仅适用于 DGX-1 和 DGX Station。

    复制
    已复制!
                

    docker run --gpus all -ti nvidian_sas/caffe_octave:17.04

    复制
    已复制!
                

    ================== == NVIDIA Caffe == ================== NVIDIA Release 17.04 (build 26740) Container image Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. Copyright (c) 2014, 2015, The Regents of the University of California (Regents) All rights reserved. Various files include modifications (c) NVIDIA CORPORATION. All rights reserved. NVIDIA modifications are covered by the license terms that apply to the underlying project or file. NOTE: The SHMEM allocation limit is set to the default of 64MB. This may be insufficient for NVIDIA Caffe. NVIDIA recommends the use of the following flags: docker run --gpus all --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 ... root@2fc3608ad9d8:/workspace# octave octave: X11 DISPLAY environment variable not set octave: disabling GUI features GNU Octave, version 4.0.0 Copyright (C) 2015 John W. Eaton and others. This is free software; see the source code for copying conditions. There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, type 'warranty'. Octave was configured for "x86_64-pc-linux-gnu". Additional information about Octave is available at http://www.octave.org. Please contribute if you find this software useful. For more information, visit http://www.octave.org/get-involved.html Read http://www.octave.org/bugs.html to learn how to submit bug reports. For information about changes from previous versions, type 'news'. octave:1>

    由于显示了 Octave 提示符,因此已安装 Octave。

  9. 如果您想将容器保存到您的私有存储库中(Docker 使用短语“push”),则可以使用命令 docker push ...
    复制
    已复制!
                

    $ docker push nvcr.io/nvidian_sas/caffe_octave:17.04

结果

新的 Docker 镜像现在可以使用了。您可以检查本地 Docker 存储库以查找它。

10.1.5. 示例 4:使用 Docker 开发容器

关于此任务

开发人员扩展容器主要有两种用例:

  1. 创建一个开发镜像,其中包含项目的所有不可变依赖项,但不包含源代码本身。
  2. 创建一个生产或测试镜像,其中包含源代码的固定版本和所有软件依赖项。

数据集未打包在容器镜像中。理想情况下,容器镜像的设计应期望数据集和结果的卷挂载。

在这些示例中,我们将本地数据集从主机上的 /raid/datasets 挂载到容器内的 /dataset 作为只读卷。我们还挂载一个特定于作业的目录,以捕获当前运行的输出。

在这些示例中,我们将在每次容器启动时创建一个带时间戳的输出目录,并将其映射到容器中的 /output。使用此方法,将捕获并隔离每次连续容器启动的输出。

将源代码包含在容器中以开发和迭代模型会带来许多挑战,这些挑战可能会使整个工作流程过于复杂。例如,如果您的源代码在容器中,那么您的编辑器、版本控制软件、点文件等也需要位于容器中。

但是,如果您创建一个开发镜像,其中包含运行源代码所需的一切,则可以将源代码映射到容器中,以利用主机工作站的开发人员环境。为了共享模型的固定版本,最好将源代码和训练权重的版本化副本与开发环境一起打包。

作为示例,我们将完成一个开发和交付示例,该示例针对 Isola 等人撰写的 Image-to-Image Translation with Conditional Adversarial Networks 中发现的工作的开源实现,可在 pix2pix 中找到。Pix2Pix 是一种 Torch 实现,用于学习从输入图像到输出图像的映射,方法是使用条件对抗网络。由于在线项目可能会随时间变化,因此我们将重点关注快照版本 d7e7b8b557229e75140cbe42b7f5dbf85a67d097 变更集。在本节中,我们将容器用作虚拟环境,因为容器具有项目所需的所有程序和库。

注意

我们将网络定义和训练脚本与容器镜像分开保存。这对于迭代开发非常有用,因为正在积极处理的文件持久保存在主机上,并且仅在运行时映射到容器中。


与原始项目的差异可以在这里找到:比较更改

如果您正在开发的机器与您将运行长时间训练会话的机器不是同一台机器,那么您可能希望将当前的开发状态打包到容器中。

步骤

  1. 在本地硬盘驱动器上创建一个工作目录。
    复制
    已复制!
                

    mkdir Projects $ cd ~/Projects

  2. Git 克隆 Pix2Pix Git 存储库。
    复制
    已复制!
                

    $ git clone https://github.com/phillipi/pix2pix.git $ cd pix2pix

  3. 运行 git checkout 命令。
    复制
    已复制!
                

    $ git checkout -b devel d7e7b8b557229e75140cbe42b7f5dbf85a67d097

  4. 下载数据集。
    复制
    已复制!
                

    bash ./datasets/download_dataset.sh facades I want to put the dataset on my fast /raid storage. $ mkdir -p /raid/datasets $ mv ./datasets/facades /raid/datasets

  5. 创建一个名为 Dockerfile 的文件,并添加以下行
    复制
    已复制!
                

    FROM nvcr.io/nvidia/torch:17.03 RUN luarocks install nngraph RUN luarocks install https://raw.githubusercontent.com/szym/display/master/display-scm-0.rockspec WORKDIR /source

  6. 构建开发 Docker 容器镜像 (build-devel.sh)。
    复制
    已复制!
                

    docker build -t nv/pix2pix-torch:devel .

  7. 创建以下 train.sh 脚本
    复制
    已复制!
                

    #!/bin/bash -x ROOT="${ROOT:-/source}" DATASET="${DATASET:-facades}" DATA_ROOT="${DATA_ROOT:-/datasets/$DATASET}" DATA_ROOT=$DATA_ROOT name="${DATASET}_generation" which_direction=BtoA th train.lua

    如果您实际上正在开发此模型,您将通过更改主机上的文件并运行在容器内执行的训练脚本来进行迭代。

  8. 可选:在每次更改后编辑文件并执行下一步。
  9. 运行训练脚本 (run-devel.sh)。
    复制
    已复制!
                

    docker run --gpus all --rm -ti -v $PWD:/source -v /raid/datasets:/datasets nv/pix2pix-torch:devel ./train.sh

示例 4.1:将源代码打包到容器中

关于此任务

将模型定义和脚本打包到容器中非常简单。我们只需在 Dockerfile 中添加一个 COPY 步骤即可。

我们已更新运行脚本,只需删除卷挂载并使用容器中打包的源代码即可。打包的容器现在比我们的 devel 容器镜像更具可移植性,因为内部代码是固定的。最好使用特定标签对该容器镜像进行版本控制,并将其存储在容器注册表中。

容器运行的更新同样微妙。我们只需删除将本地源代码卷挂载到容器中即可。

10.2. 定制框架

每个 Docker 镜像都包含构建框架所需的代码,以便您可以更改框架本身。每个镜像中框架源代码的位置都在 /workspace 目录中。

有关特定目录位置,请参阅您的特定框架的深度学习框架发行说明

10.2.1. 定制框架的优点和局限性

如果您有想要在 NVIDIA 存储库之外对框架进行的补丁或修改,或者您有想要添加到框架的特殊补丁,则定制框架非常有用。

10.2.2. 示例 1:使用命令行定制框架

关于此任务

此 Dockerfile 示例说明了一种将补丁应用于 NVCaffe 容器镜像中源代码并重建 NVCaffe 的方法。下面包含的 RUN 命令将以与原始镜像中构建 NVCaffe 相同的方式重建 NVCaffe。

通过以这种方式通过 Dockerfile 和 docker build 应用定制,而不是以交互方式修改容器,可以轻松地将相同的更改应用于更高版本的 NVCaffe 容器镜像。

有关更多信息,请参阅Dockerfile 参考

步骤

  1. 为 Dockerfile 创建一个工作目录。
    复制
    已复制!
                

    $ mkdir docker $ cd docker

  2. 打开文本编辑器并创建一个名为 Dockerfile 的文件,并添加以下行
    复制
    已复制!
                

    FROM nvcr.io/nvidia/caffe:17.04 RUN apt-get update && apt-get install bc

  3. 将容器外部的更改引入到 /tmp
    注意

    这假定 my-caffe-modifications.patch 与 Dockerfile 位于同一目录中。

    复制
    已复制!
                

    COPY my-caffe-modifications.patch /tmp

  4. 将您的工作目录更改为 NVCaffe 源代码路径。
    复制
    已复制!
                

    WORKDIR /opt/caffe

  5. 应用您的修改。
    复制
    已复制!
                

    RUN patch -p1 < /tmp/my-caffe-modifications.patch

  6. 重建 NVCaffe。
    复制
    已复制!
                

    RUN mkdir build && cd build && \ cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr/local -DUSE_NCCL=ON -DUSE_CUDNN=ON \ -DCUDA_ARCH_NAME=Manual -DCUDA_ARCH_BIN="35 52 60 61" -DCUDA_ARCH_PTX="61" .. && \ make -j"$(nproc)" install && \ make clean && \ cd .. && rm -rf build

  7. 重置默认工作目录。
    复制
    已复制!
                

    WORKDIR /workspace

示例 2:定制框架并重建容器

关于此任务

此示例说明了如何定制框架并重建容器。对于此示例,我们将使用 NVCaffe 17.03 框架。当前,当创建网络层时,NVCaffe 框架将以下输出消息返回到 stdout

复制
已复制!
            

“Creating Layer”


例如,您可以通过从 NVCaffe 17.03 容器中的 bash shell 运行以下命令来查看此输出。

复制
已复制!
            

# which caffe /usr/local/bin/caffe # caffe time --model /workspace/models/bvlc_alexnet/deploy.prototxt --gpu=0 … I0523 17:57:25.603410 41 net.cpp:161] Created Layer data (0) I0523 17:57:25.603426 41 net.cpp:501] data -> data I0523 17:57:25.604748 41 net.cpp:216] Setting up data …


以下步骤向您展示了如何将 NVCaffe 中的消息 “Created Layer” 更改为 “Just Created Layer”。此示例说明了您可能如何修改现有框架。

开始之前

确保在交互模式下运行框架容器。

步骤

  1. nvcr.io 存储库中找到 NVCaffe 17.03 容器。
    复制
    已复制!
                

    $ docker pull nvcr.io/nvidia/caffe:17.03

  2. 在 DGX 系统上运行容器。
    复制
    已复制!
                

    docker run --gpus all --rm -ti nvcr.io/nvidia/caffe:17.03

    注意

    这将使您成为容器中的 root 用户。注意提示符的变化。

  3. 编辑 NVCaffe 源文件 /opt/caffe/src/caffe/net.cpp 中的文件。您要更改的行大约在第 162 行。
    复制
    已复制!
                

    # vi /opt/caffe/src/caffe/net.cpp :162 s/Created Layer/Just Created Layer

    注意

    这使用 vi。将 “Created Layer” 更改为 “Just Created Layer”

  4. 重建 NVCaffe。
    复制
    已复制!
                

    # cd /opt/caffe # cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr/local -DUSE_NCCL=ON -DUSE_CUDNN=ON -DCUDA_ARCH_NAME=Manual -DCUDA_ARCH_BIN="35 52 60 61" -DCUDA_ARCH_PTX="61" .. # make -j"$(proc)" install # make install # ldconfig

  5. 在运行更新后的 NVCaffe 框架之前,请确保更新后的 NVCaffe 二进制文件位于正确的位置,例如 /usr/local/
    复制
    已复制!
                

    # which caffe /usr/local/bin/caffe

  6. 运行 NVCaffe 并查找 stdout 输出中的更改
    复制
    已复制!
                

    # caffe time --model /workspace/models/bvlc_alexnet/deploy.prototxt --gpu=0 /usr/local/bin/caffe … I0523 18:29:06.942697 7795 net.cpp:161] Just Created Layer data (0) I0523 18:29:06.942711 7795 net.cpp:501] data -> data I0523 18:29:06.944180 7795 net.cpp:216] Setting up data ...

  7. 将您的容器保存到 nvcr.io 上的私有 DGX 存储库或您的私有 Docker 存储库(有关示例,请参阅示例 2:使用 Dockerfile 定制容器)。

10.3. 优化 Docker 容器大小

使用分层的 Docker 容器格式专门设计用于限制在实例化容器镜像时需要传输的数据量。当从存储库实例化或“拉取”Docker 容器镜像时,Docker 可能需要将层从存储库复制到本地主机。它使用每个层的哈希值检查本地主机上已有的层。如果本地主机上已经有该层,则不会“重新下载”它,从而节省时间,并在较小程度上节省网络使用量。

这对于 NVIDIA 的 NGC 特别有用,因为所有容器都是使用相同的基本操作系统和库构建的。如果您从 NGC 运行一个容器镜像,然后运行另一个容器镜像,则第一个容器中的许多层很可能在第二个容器中使用,从而减少了拉取第二个容器镜像的时间,以便可以快速启动容器。

您可以将几乎任何您想要的东西放入容器中,从而允许用户或容器开发人员创建非常大的 (GB+) 容器。即使不建议将数据放入 Docker 容器镜像中,用户和开发人员也会这样做(有一些很好的理由)。这会进一步增加容器镜像的大小。这会增加下载容器镜像或其各个层的时间。用户和开发人员现在正在寻求减少容器镜像或各个层大小的方法。

以下小节介绍了一些选项,如果容器镜像或层大小太大,或者您希望它们更小,则可以使用这些选项。没有一个最佳选项,因此请务必在您的容器镜像上尝试它们。

10.3.1. 每个命令一行 RUN 命令

在 Dockerfile 中,为每个 RUN 命令使用一行非常方便。代码易于阅读,因为您可以看到每个命令。但是,Docker 将为每个命令创建一个层。每个层都保留有关其来源、层创建时间、层中包含的内容以及每个层的哈希值的一些信息(元数据)。如果您有大量命令,那么您将有大量元数据。

减少容器镜像大小的一种简单方法是将您可以放入单个 RUN 语句中的所有 RUN 命令都放入其中。这可能会导致非常大的 RUN 命令,但是,它大大减少了元数据量。建议您尽可能将多个 RUN 命令组合在一起。根据您的 Dockerfile,您可能无法将所有 RUN 命令放入单个 RUN 语句中。尽力减少 RUN 命令的数量,但使其符合逻辑。下面是一个用于构建容器镜像的简单 Dockerfile 示例。

复制
已复制!
            

$ cat Dockerfile FROM ubuntu:20.04 RUN date > /build-info.txt RUN uname -r >> /build-info.txt Notice there are two RUN commands in this simple Dockerfile. The container image can be built using the following command and associated output. $ docker build -t first-image -f Dockerfile . … Step 2/3 : RUN date > /build-info.txt ---> Using cache ---> af12c4b34f91 Step 3/3 : RUN uname -r >> /build-info.txt ---> Running in 0f883f37e3c8 …

请注意,RUN 命令在容器镜像中各创建了一个层。
让我们检查容器镜像以获取有关层的详细信息。

复制
已复制!
            

$ docker run --rm -it first-image cat /build-info.txt Mon Jan 18 10:14:02 UTC 2021 5.5.115-1.el7.elrepo.x86_64 $ docker history first-image IMAGE CREATED CREATED BY SIZE d2c03aa61290 11 seconds ago /bin/sh -c uname -r >> /build-info.txt 57B af12c4b34f91 16 minutes ago /bin/sh -c date > /build-info.txt 29B 5e8b97a2a082 6 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 6 weeks ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B <missing> 6 weeks ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$… 2.76kB <missing> 6 weeks ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0B <missing> 6 weeks ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 745B <missing> 6 weeks ago /bin/sh -c #(nop) ADD file:d37ff24540ea7700d… 114MB

此命令的输出为您提供有关每个层的信息。请注意,每个 RUN 命令都有一个层。
现在,让我们获取 Dockerfile 并组合两个 RUN 命令。

复制
已复制!
            

$ cat Dockerfile FROM ubuntu:20.04 RUN date > /build-info.txt && uname -r >> /build-info.txt $ docker build -t one-layer -f Dockerfile . $ docker history one-layer IMAGE CREATED CREATED BY SIZE 3b1ef5bc19b2 6 seconds ago /bin/sh -c date > /build-info.txt && uname -… 57B 5e8b97a2a082 6 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 6 weeks ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B <missing> 6 weeks ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$… 2.76kB <missing> 6 weeks ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0B <missing> 6 weeks ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 745B <missing> 6 weeks ago /bin/sh -c #(nop) ADD file:d37ff24540ea7700d… 114MB

请注意,现在只有一个层包含两个 RUN 命令。

RUN 命令组合在一起的另一个好处是,如果您有多个层,则可以轻松修改容器镜像中的一个层,而无需修改整个容器镜像。

10.3.2. 导出、导入和展平

如果空间有限,有一种方法可以获取现有的容器镜像,并去除所有历史记录。这只能通过运行中的容器来完成。容器运行后,运行以下两个命令

复制
已复制!
            

# export the container to a tarball docker export <CONTAINER ID> > /home/export.tar # import it back cat /home/export.tar | docker import - some-name:<tag>

这将去除每个层的历史记录,但会保留层(如果这很重要)。
另一种选择是将您的镜像“展平”为单层。这会去除层中的所有冗余,并创建一个单层容器。与之前的技术一样,此技术也需要运行中的容器。在容器运行时,发出以下命令

复制
已复制!
            

docker export <CONTAINER ID> | docker import - some-image-name:<tag>


此管道通过 import 命令导出容器,从而创建一个仅有一层的新容器。有关更多信息,请参阅这篇博客文章

10.3.3.  docker-squash

几年前,在 Docker 出现之前,添加了通过名为 docker-squash 的工具“压缩”镜像的功能。虽然它已经几年没有更新了,但它仍然是用于减小 Docker 容器镜像大小的流行工具。该工具接受 Docker 容器镜像并将其“压缩”为单层,减少层之间的共性以及层的历史记录,从而生成尽可能小的容器镜像。

该工具保留了 Docker 命令,例如 PORTENV 等。压缩后的镜像与压缩前的工作方式完全相同。此外,在压缩过程中删除的文件实际上已从镜像中删除。以下是运行 docker-squash 的简单示例。

复制
已复制!
            

docker save <ID> | docker-squash -t <TAG> [-from <ID>] | docker load


此管道获取当前镜像,保存它,使用新标签压缩它,然后重新加载容器。生成的镜像将初始 FROM 层之下的所有层压缩为单层。 docker-squash 中的默认选项保留了基础镜像层,以便在推送和拉取镜像更新时无需重复传输。

该工具实际上是为已完成且不太可能更新的容器设计的。因此,几乎不需要有关层和历史记录的详细信息。然后可以将其压缩并投入生产。拥有最小尺寸的镜像将允许用户快速下载镜像并使其运行,因为它几乎尽可能小。

10.3.4. 构建时压缩

Docker 问世后不久,人们开始创建占用大量传输时间的巨型镜像。那时,用户和开发人员开始研究减小容器大小的想法。不久前,有人为 Docker 提出了补丁,允许在构建时压缩镜像。 squash 选项已添加到 Docker 1.13 (API 1.25) 中,当时 Docker 仍然遵循不同的版本控制方案。截至 Docker 17.06‑ce,该选项仍被归类为实验性功能。如果您愿意,可以告诉 Docker 允许使用实验性选项(请参阅 Docker 文档)。但是,NVIDIA 不支持此选项。 --squash 选项在构建容器时使用。以下是命令示例

复制
已复制!
            

docker build --squash -t chamilad/testdocker:0.1 .


此命令使用“Dockerfile”作为构建容器的 dockerfile。

--squash 选项创建一个包含两层的镜像。第一层来自通常启动 Dockerfile 的 FROM。后续层都“压缩”到单层中。这会去除除第一层之外所有层中的历史记录。它还消除了冗余文件。

由于它仍然是一项实验性功能,因此您可以压缩镜像的程度各不相同。据报道,镜像大小减少了 50%。

10.3.5. 其他选项

还有一些其他选项可用于减小镜像的大小,但它们并非特别基于 Docker(尽管有几个是)。其余的是经典的 Linux 命令。

有一个 Docker 构建选项用于处理在 Docker 容器中构建应用程序。如果您希望在创建容器时构建应用程序,您可能不希望将构建工具留在镜像中,因为它的体积很大。当容器应该被执行而不是在运行时被修改时,情况确实如此。回想一下,Docker 容器是分层构建的。我们可以在构建容器时使用这个事实,将二进制文件从一层复制到另一层。例如,下面的 Docker 文件

复制
已复制!
            

$ cat Dockerfile FROM ubuntu:20.04 RUN apt-get update -y && \ apt-get install -y --no-install-recommends \ build-essential \ gcc && \ rm -rf /var/lib/apt/lists/* COPY hello.c /tmp/hello.c RUN gcc -o /tmp/hello /tmp/hello.c

构建一个容器,安装 gcc,并构建一个简单的“hello world”应用程序。检查容器的历史记录将为我们提供层的大小

复制
已复制!
            

$ docker history hello IMAGE CREATED CREATED BY SIZE 49fef0e11806 8 minutes ago /bin/sh -c gcc -o /tmp/hello /tmp/hello.c 8.6kB 44a449445055 8 minutes ago /bin/sh -c #(nop) COPY file:8f0c1776b2571c38… 63B c2e5b659a549 8 minutes ago /bin/sh -c apt-get update -y && apt-get … 181MB 5e8b97a2a082 6 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 6 weeks ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B <missing> 6 weeks ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$… 2.76kB <missing> 6 weeks ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0B <missing> 6 weeks ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 745B <missing> 6 weeks ago /bin/sh -c #(nop) ADD file:d37ff24540ea7700d… 114MB


请注意,包含构建工具的层大小为 181MB,而应用程序层大小仅为 8.6kB。如果最终容器中不需要构建工具,那么我们可以从镜像中删除它。但是,如果您只是执行 apt-get remove … 命令,则构建工具实际上并未被擦除。一种解决方案是将二进制文件从上一层复制到新层,如下面的 Dockerfile 所示

复制
已复制!
            

$ cat Dockerfile FROM ubuntu:16.04 AS build RUN apt-get update -y && \ apt-get install -y --no-install-recommends \ build-essential \ gcc && \ rm -rf /var/lib/apt/lists/* COPY hello.c /tmp/hello.c RUN gcc -o /tmp/hello /tmp/hello.c FROM ubuntu:16.04 COPY --from=build /tmp/hello /tmp/hello


这可以称为“多阶段”构建。在此 Dockerfile 中,第一阶段从操作系统开始,并将其命名为“build”。然后安装构建工具,将源代码复制到容器中,并构建二进制文件。

下一层从全新的操作系统 FROM 命令(称为“第一阶段”)开始。Docker 将仅保存从此层开始的层和任何后续层(换句话说,安装构建工具的第一层将不会被保存)或“第二阶段”。第二阶段可以从第一阶段复制二进制文件。此阶段不包含任何构建工具。构建容器镜像与之前相同。如果我们比较使用第一个 Dockerfile 的容器大小与使用第二个 Dockerfile 的大小,我们可以看到以下内容

复制
已复制!
            

$ docker images hello REPOSITORY TAG IMAGE ID CREATED SIZE hello latest 49fef0e11806 21 minutes ago 295MB $ docker images hello-rt REPOSITORY TAG IMAGE ID CREATED SIZE hello-rt latest f0cef59a05dd 2 minutes ago 114MB

第一个输出是原始 Dockerfile。第二个输出是用于多阶段 Dockerfile 的。请注意两者之间的大小差异。

减小 Docker 容器大小的一种选择是从小型基础镜像开始。通常,发行版的基础镜像相当精简,但查看镜像中安装了哪些内容可能是一个好主意。如果有一些不需要的东西,您可以尝试创建自己的基础镜像来删除不需要的工具。

另一种选择是运行命令 apt-get clean 来清理镜像中可能存在的任何软件包缓存。

TensorFlow

11.1.1.  run_tf_cifar10.sh


复制
已复制!
            

#!/bin/bash # file: run_tf_cifar10.sh # run example: # ./run_kerastf_cifar10.sh --epochs=3 --datadir=/datasets/cifar # Get usage help via: # ./run_kerastf_cifar10.sh --help 2>/dev/null _basedir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # specify workdirectory for the container to run scripts or work from. workdir=$_basedir cifarcode=${_basedir}/examples/tensorflow/cifar/cifar10_multi_gpu_train.py # cifarcode=${_basedir}/examples/tensorflow/cifar/cifar10_train.py function join { local IFS="$1"; shift; echo "$*"; } script_args=$(join : "$@") dname=${USER}_tf docker run --gpus all --name=$dname -d -t \ --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 \ -u $(id -u):$(id -g) -e HOME=$HOME -e USER=$USER -v $HOME:$HOME \ -v /datasets/cifar:/datasets/cifar:ro -w $workdir \ -e cifarcode=$cifarcode -e script_args="$script_args" \ nvcr.io/nvidia/tensorflow:17.05 sleep 1 # wait for container to come up docker exec -it $dname bash -c 'python $cifarcode ${script_args//:/ }' docker stop $dname && docker rm $dname

11.2. Keras

11.2.1.  cifar10_cnn_filesystem.py


复制
已复制!
            

#!/usr/bin/env python # file: cifar10_cnn_filesystem.py ''' Train a simple deep CNN on the CIFAR10 small images dataset. ''' from __future__ import print_function import sys import os from argparse import (ArgumentParser, SUPPRESS) from textwrap import dedent import numpy as np # from keras.utils.data_utils import get_file from keras.utils import to_categorical from keras.datasets import cifar10 from keras.preprocessing.image import ImageDataGenerator from keras.models import Sequential import keras.layers as KL from keras import backend as KB from keras.optimizers import RMSprop def parser_(desc): parser = ArgumentParser(description=dedent(desc)) parser.add_argument('--epochs', type=int, default=200, help='Number of epochs to run training for.') parser.add_argument('--aug', action='store_true', default=False, help='Perform data augmentation on cifar10 set.\n') # parser.add_argument('--datadir', default='/mnt/datasets') parser.add_argument('--datadir', default=SUPPRESS, help='Data directory with Cifar10 dataset.') args = parser.parse_args() return args def make_model(inshape, num_classes): model = Sequential() model.add(KL.InputLayer(input_shape=inshape[1:])) model.add(KL.Conv2D(32, (3, 3), padding='same')) model.add(KL.Activation('relu')) model.add(KL.Conv2D(32, (3, 3))) model.add(KL.Activation('relu')) model.add(KL.MaxPooling2D(pool_size=(2, 2))) model.add(KL.Dropout(0.25)) model.add(KL.Conv2D(64, (3, 3), padding='same')) model.add(KL.Activation('relu')) model.add(KL.Conv2D(64, (3, 3))) model.add(KL.Activation('relu')) model.add(KL.MaxPooling2D(pool_size=(2, 2))) model.add(KL.Dropout(0.25)) model.add(KL.Flatten()) model.add(KL.Dense(512)) model.add(KL.Activation('relu')) model.add(KL.Dropout(0.5)) model.add(KL.Dense(num_classes)) model.add(KL.Activation('softmax')) return model def cifar10_load_data(path): """Loads CIFAR10 dataset. # Returns Tuple of Numpy arrays: `(x_train, y_train), (x_test, y_test)`. """ dirname = 'cifar-10-batches-py' # origin = 'http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz' # path = get_file(dirname, origin=origin, untar=True) path_ = os.path.join(path, dirname) num_train_samples = 50000 x_train = np.zeros((num_train_samples, 3, 32, 32), dtype='uint8') y_train = np.zeros((num_train_samples,), dtype='uint8') for i in range(1, 6): fpath = os.path.join(path_, 'data_batch_' + str(i)) data, labels = cifar10.load_batch(fpath) x_train[(i - 1) * 10000: i * 10000, :, :, :] = data y_train[(i - 1) * 10000: i * 10000] = labels fpath = os.path.join(path_, 'test_batch') x_test, y_test = cifar10.load_batch(fpath) y_train = np.reshape(y_train, (7, 1)) y_test = np.reshape(y_test, (6, 1)) if KB.image_data_format() == 'channels_last': x_train = x_train.transpose(0, 2, 3, 1) x_test = x_test.transpose(0, 2, 3, 1) return (x_train, y_train), (x_test, y_test) def main(argv=None): ''' ''' main.__doc__ = __doc__ argv = sys.argv if argv is None else sys.argv.extend(argv) desc = main.__doc__ # CLI parser args = parser_(desc) batch_size = 32 num_classes = 10 epochs = args.epochs data_augmentation = args.aug datadir = getattr(args, 'datadir', None) # The data, shuffled and split between train and test sets: (x_train, y_train), (x_test, y_test) = cifar10_load_data(datadir) \ if datadir is not None else cifar10.load_data() print(x_train.shape[0], 'train samples') print(x_test.shape[0], 'test samples') # Convert class vectors to binary class matrices. y_train = to_categorical(y_train, num_classes) y_test = to_categorical(y_test, num_classes) x_train = x_train.astype('float32') x_test = x_test.astype('float32') x_train /= 255 x_test /= 255 callbacks = None print(x_train.shape, 'train shape') model = make_model(x_train.shape, num_classes) print(model.summary()) # initiate RMSprop optimizer opt = RMSprop(lr=0.0001, decay=1e-6) # Let's train the model using RMSprop model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy']) nsamples = x_train.shape[0] steps_per_epoch = nsamples // batch_size if not data_augmentation: print('Not using data augmentation.') model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_data=(x_test, y_test), shuffle=True, callbacks=callbacks) else: print('Using real-time data augmentation.') # This will do preprocessing and realtime data augmentation: datagen = ImageDataGenerator( # set input mean to 0 over the dataset featurewise_center=False, samplewise_center=False, # set each sample mean to 0 # divide inputs by std of the dataset featurewise_std_normalization=False, # divide each input by its std samplewise_std_normalization=False, zca_whitening=False, # apply ZCA whitening # randomly rotate images in the range (degrees, 0 to 180) rotation_range=0, # randomly shift images horizontally (fraction of total width) width_shift_range=0.1, # randomly shift images vertically (fraction of total height) height_shift_range=0.1, horizontal_flip=True, # randomly flip images vertical_flip=False) # randomly flip images # Compute quantities required for feature-wise normalization # (std, mean, and principal components if ZCA whitening is applied). datagen.fit(x_train) # Fit the model on the batches generated by datagen.flow(). model.fit_generator(datagen.flow(x_train, y_train, batch_size=batch_size), steps_per_epoch=steps_per_epoch, epochs=epochs, validation_data=(x_test, y_test), callbacks=callbacks) if __name__ == '__main__': main()


有关 Docker 容器的更多信息,请参阅

有关深度学习框架发行说明和其他产品文档,请参阅深度学习文档网站:深度学习框架文档

声明

本文档仅供参考,不应视为对产品的特定功能、条件或质量的保证。NVIDIA Corporation(“NVIDIA”)对本文档中包含信息的准确性或完整性不作任何明示或暗示的陈述或保证,并且对本文档中包含的任何错误不承担任何责任。NVIDIA 对使用此类信息造成的后果或使用此类信息,或因其使用而可能导致的侵犯第三方专利或其他权利的行为不承担任何责任。本文档不构成对开发、发布或交付任何材料(如下所定义)、代码或功能的承诺。

NVIDIA 保留随时修改、增强、改进本文档以及对其进行任何其他更改的权利,恕不另行通知。

客户应在下订单前获取最新的相关信息,并应确认此类信息是最新且完整的。

NVIDIA 产品根据订单确认时提供的 NVIDIA 标准销售条款和条件进行销售,除非 NVIDIA 和客户的授权代表签署的个别销售协议(“销售条款”)另有约定。NVIDIA 在此明确反对将任何客户通用条款和条件应用于购买本文档中引用的 NVIDIA 产品。本文档不直接或间接地形成任何合同义务。

NVIDIA 产品并非设计、授权或保证适用于医疗、军事、航空、航天或生命维持设备,也不适用于 NVIDIA 产品的故障或失灵可能合理预期会导致人身伤害、死亡或财产或环境损害的应用。NVIDIA 对在上述设备或应用中包含和/或使用 NVIDIA 产品不承担任何责任,因此,此类包含和/或使用风险由客户自行承担。

NVIDIA 不保证或声明基于本文档的产品将适用于任何特定用途。NVIDIA 不一定会执行每个产品所有参数的测试。客户有责任评估和确定本文档中包含的任何信息的适用性,确保产品适合并符合客户计划的应用,并为该应用执行必要的测试,以避免应用或产品的默认设置。客户产品设计中的缺陷可能会影响 NVIDIA 产品的质量和可靠性,并可能导致超出本文档中包含的附加或不同条件和/或要求。NVIDIA 对任何可能基于以下原因或归因于以下原因的默认设置、损坏、成本或问题不承担任何责任:(i) 以任何与本文档相悖的方式使用 NVIDIA 产品,或 (ii) 客户产品设计。

本文档未授予 NVIDIA 专利权、版权或其他 NVIDIA 知识产权下的任何明示或暗示的许可。NVIDIA 发布的有关第三方产品或服务的信息不构成 NVIDIA 授予使用此类产品或服务的许可,也不构成对其的保证或认可。使用此类信息可能需要获得第三方专利或第三方其他知识产权下的许可,或获得 NVIDIA 专利或 NVIDIA 其他知识产权下的许可。

仅当事先获得 NVIDIA 书面批准,未经修改且完全符合所有适用的出口法律和法规进行复制,并附带所有相关的条件、限制和声明时,才允许复制本文档中的信息。

本文档和所有 NVIDIA 设计规范、参考板、文件、图纸、诊断程序、列表和其他文档(统称为“材料”,单独或合并)均按“原样”提供。NVIDIA 对材料不作任何明示、暗示、法定或其他形式的保证,并明确否认所有关于不侵权、适销性和特定用途适用性的暗示保证。在法律未禁止的范围内,在任何情况下,NVIDIA 均不对因使用本文档而引起的任何损害(包括但不限于任何直接、间接、特殊、偶然、惩罚性或后果性损害,无论如何造成,也无论责任理论如何)承担责任,即使 NVIDIA 已被告知发生此类损害的可能性。尽管客户可能因任何原因而遭受任何损害,但 NVIDIA 对本文所述产品的客户承担的总体和累积责任应根据产品的销售条款进行限制。

HDMI

HDMI、HDMI 徽标和 High-Definition Multimedia Interface 是 HDMI Licensing LLC 的商标或注册商标。

OpenCL

OpenCL 是 Apple Inc. 的商标,已获得 Khronos Group Inc. 的许可使用。

商标

NVIDIA、NVIDIA 徽标以及 cuBLAS、CUDA、DALI、DGX、DGX-1、DGX-2、DGX Station、DLProf、Jetson、Kepler、Maxwell、NCCL、Nsight Compute、Nsight Systems、NvCaffe、PerfWorks、Pascal、SDK Manager、Tegra、TensorRT、Triton Inference Server、Tesla、TF-TRT 和 Volta 是 NVIDIA Corporation 在美国和其他国家/地区的商标和/或注册商标。其他公司和产品名称可能是与其相关联的各自公司的商标。

© 2017-2025 NVIDIA Corporation 和/或其附属公司。保留所有权利。 上次更新时间:2025 年 1 月 29 日。