你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

在 Azure Stack Edge Pro 上使用 GPU 共享部署 IoT Edge 工作负载

本文介绍容器化工作负载如何在 Azure Stack Edge Pro GPU 设备上共享 GPU。 方法涉及启用多进程服务 (MPS) 然后通过 IoT Edge 部署指定 GPU 工作负载。

先决条件

在开始之前,请确保:

  1. 可以访问已激活配置了计算的 Azure Stack Edge Pro GPU 设备。 你具有 Kubernetes API 终结点,并且已将此终结点添加到要访问设备的客户端上的 hosts 文件。

  2. 你可以使用受支持的操作系统访问客户端系统。 如果使用 Windows 客户端,则系统应运行 PowerShell 5.0 或更高版本来访问设备。

  3. 在本地系统上保存以下部署 json 文件。 你将使用此文件中的信息来运行 IoT Edge 部署。 此部署基于 Nvidia 公开提供的简单 CUDA 容器

    {
        "modulesContent": {
            "$edgeAgent": {
                "properties.desired": {
                    "modules": {
                        "cuda-sample1": {
                            "settings": {
                                "image": "nvidia/samples:nbody",
                                "createOptions": "{\"Entrypoint\":[\"/bin/sh\"],\"Cmd\":[\"-c\",\"/tmp/nbody -benchmark -i=1000; while true; do echo no-op; sleep 10000;done\"],\"HostConfig\":{\"IpcMode\":\"host\",\"PidMode\":\"host\"}}"
                            },
                            "type": "docker",
                            "version": "1.0",
                            "env": {
                                "NVIDIA_VISIBLE_DEVICES": {
                                    "value": "0"
                                }
                            },
                            "status": "running",
                            "restartPolicy": "never"
                        },
                        "cuda-sample2": {
                            "settings": {
                                "image": "nvidia/samples:nbody",
                                "createOptions": "{\"Entrypoint\":[\"/bin/sh\"],\"Cmd\":[\"-c\",\"/tmp/nbody -benchmark -i=1000; while true; do echo no-op; sleep 10000;done\"],\"HostConfig\":{\"IpcMode\":\"host\",\"PidMode\":\"host\"}}"
                            },
                            "type": "docker",
                            "version": "1.0",
                            "env": {
                                "NVIDIA_VISIBLE_DEVICES": {
                                    "value": "0"
                                }
                            },
                            "status": "running",
                            "restartPolicy": "never"
                        }
                    },
                    "runtime": {
                        "settings": {
                            "minDockerVersion": "v1.25"
                        },
                        "type": "docker"
                    },
                    "schemaVersion": "1.1",
                    "systemModules": {
                        "edgeAgent": {
                            "settings": {
                                "image": "mcr.microsoft.com/azureiotedge-agent:1.0",
                                "createOptions": ""
                            },
                            "type": "docker"
                        },
                        "edgeHub": {
                            "settings": {
                                "image": "mcr.microsoft.com/azureiotedge-hub:1.0",
                                "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"443\"}],\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}]}}}"
                            },
                            "type": "docker",
                            "status": "running",
                            "restartPolicy": "always"
                        }
                    }
                }
            },
            "$edgeHub": {
                "properties.desired": {
                    "routes": {
                        "route": "FROM /messages/* INTO $upstream"
                    },
                    "schemaVersion": "1.1",
                    "storeAndForwardConfiguration": {
                        "timeToLiveSecs": 7200
                    }
                }
            },
            "cuda-sample1": {
                "properties.desired": {}
            },
            "cuda-sample2": {
                "properties.desired": {}
            }
        }
    }
    

验证 GPU 驱动程序、CUDA 版本

第一步是验证设备是否正在运行所需的 GPU 驱动程序和 CUDA 版本。

  1. 连接到设备的 PowerShell 界面

  2. 运行以下命令:

    Get-HcsGpuNvidiaSmi

  3. 在 Nvidia smi 输出中,记下设备上的 GPU 版本和 CUDA 版本。 如果正在运行 Azure Stack Edge 2102 软件,此版本将与以下驱动程序版本相对应:

    • GPU 驱动程序版本:460.32.03
    • CUDA 版本:11.2

    下面是示例输出:

    [10.100.10.10]: PS>Get-HcsGpuNvidiaSmi
    K8S-1HXQG13CL-1HXQG13:
    
    Tue Feb 23 10:34:01 2021
    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 460.32.03    Driver Version: 460.32.03    CUDA Version: 11.2     |
    |-------------------------------+----------------------+----------------------+
    | 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  Tesla T4            On   | 0000041F:00:00.0 Off |                    0 |
    | N/A   40C    P8    15W /  70W |      0MiB / 15109MiB |      0%      Default |
    |                               |                      |                  N/A |
    +-------------------------------+----------------------+----------------------+
    
    +-----------------------------------------------------------------------------+
    | Processes:                                                                  |
    |  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
    |        ID   ID                                                   Usage      |
    |=============================================================================|
    |  No running processes found                                                 |
    +-----------------------------------------------------------------------------+
    [10.100.10.10]: PS>  
    
  4. 使此会话保持打开状态,因为你在本文中将使用它来查看 Nvidia smi 输出。

不含上下文共享的部署

现在,当多进程服务未运行且没有上下文共享时,可以在设备上部署应用程序。 通过 Azure 门户,在存在于设备上的 iotedge 命名空间中部署。

在 IoT Edge 命名空间中创建用户

首先,要创建一个连接到 iotedge 命名空间的用户。 IoT Edge 模块部署在 iotedge 命名空间中。 有关详细信息,请参阅设备上的 Kubernetes 命名空间

按照以下步骤创建用户,并向用户授予对 iotedge 命名空间的访问权限。

  1. 连接到设备的 PowerShell 界面

  2. iotedge 命名空间中创建新用户。 运行以下命令:

    New-HcsKubernetesUser -UserName <user name>

    下面是示例输出:

    [10.100.10.10]: PS>New-HcsKubernetesUser -UserName iotedgeuser
    apiVersion: v1
    clusters:
    - cluster:
        certificate-authority-data: 
    ===========================//snipped //======================// snipped //=============================
        server: https://compute.myasegpudev.wdshcsso.com:6443
      name: kubernetes
    contexts:
    - context:
        cluster: kubernetes
        user: iotedgeuser
      name: iotedgeuser@kubernetes
    current-context: iotedgeuser@kubernetes
    kind: Config
    preferences: {}
    users:
    - name: iotedgeuser
      user:
        client-certificate-data: 
    ===========================//snipped //======================// snipped //=============================
        client-key-data: 
    ===========================//snipped //======================// snipped ============================
    PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
    
  3. 复制以纯文本格式显示的输出。 在本地计算机上用户配置文件的 .kube 文件夹(例如 C:\Users\<username>\.kube)中,将输出另存为 config 文件(不含扩展名)。

  4. 授权你创建的用户访问 iotedge 命名空间。 运行以下命令:

    Grant-HcsKubernetesNamespaceAccess -Namespace iotedge -UserName <user name>

    下面是示例输出:

    [10.100.10.10]: PS>Grant-HcsKubernetesNamespaceAccess -Namespace iotedge -UserName iotedgeuser
    [10.100.10.10]: PS>    
    

有关详细说明,请参阅通过 kubectl 在 Azure Stack Edge Pro GPU 设备上连接并管理 Kubernetes 群集

通过门户部署模块

通过 Azure 门户部署 IoT Edge 模块。 你将部署用于运行 n-body 模拟的公开提供的 Nvidia CUDA 示例模块。

  1. 确保 IoT Edge 服务在设备上运行。

    IoT Edge service running.

  2. 在右窗格中,选择“IoT Edge”磁贴。 转到“IoT Edge”>“属性”。 在右窗格中,选择与你的设备关联的 IoT 中心资源。

    View properties.

  3. 在 IoT 中心资源中,转到“自动设备管理”>“IoT Edge”。 在右窗格中,选择与你的设备关联的 IoT Edge 设备。

    Go to IoT Edge.

  4. 选择“设置模块”。

    Go to Set Modules.

  5. 选择“+ 添加”>“IoT Edge 模块”

    Add IoT Edge module.

  6. 在“模块设置”选项卡上,提供 IoT Edge 模块名称和映像 URI。 将“映像请求策略”设置为“创建时”。

    Module settings.

  7. 在“环境变量”选项卡上,将“NVIDIA_VISIBLE_DEVICES”指定为“0”。

    Environment variables.

  8. 在“容器创建选项”选项卡上,提供以下选项:

    {
        "Entrypoint": [
            "/bin/sh"
        ],
        "Cmd": [
            "-c",
            "/tmp/nbody -benchmark -i=1000; while true; do echo no-op; sleep 10000;done"
        ],
        "HostConfig": {
            "IpcMode": "host",
            "PidMode": "host"
        }
    }    
    

    选项如下所示:

    Container create options.

    选择添加

  9. 添加的模块应显示为“正在运行”。

    Review and create deployment.

  10. 重复添加第一个模块时所遵循的所有步骤,以添加模块。 在此示例中,提供 cuda-sample2 作为模块的名称。

    Module settings for 2nd module.

    使用相同的环境变量,因为这两个模块将共享同一个 GPU。

    Environment variable for 2nd module.

    使用为第一个模块提供的相同容器创建选项,然后选择“添加”。

    Container create options for 2nd modules.

  11. 在“设置模块”页上,选择“查看 + 创建”,然后选择“创建”。

    Review and create 2nd deployment.

  12. 这两个模块的“运行时状态”现在应显示为“正在运行”。

    2nd deployment status.

监视工作负载部署

  1. 打开新的 PowerShell 会话。

  2. 列出在 iotedge 命名空间中运行的 pod。 运行以下命令:

    kubectl get pods -n iotedge

    下面是示例输出:

    PS C:\WINDOWS\system32> kubectl get pods -n iotedge --kubeconfig C:\GPU-sharing\kubeconfigs\configiotuser1
    NAME                            READY   STATUS    RESTARTS   AGE
    cuda-sample1-869989578c-ssng8   2/2     Running   0          5s
    cuda-sample2-6db6d98689-d74kb   2/2     Running   0          4s
    edgeagent-79f988968b-7p2tv      2/2     Running   0          6d21h
    edgehub-d6c764847-l8v4m         2/2     Running   0          24h
    iotedged-55fdb7b5c6-l9zn8       1/1     Running   1          6d21h
    PS C:\WINDOWS\system32>   
    

    设备上有两个 pod(cuda-sample1-97c494d7f-lnmnscuda-sample2-d9f6c4688-2rld9)在设备上运行。

  3. 尽管两个容器都运行 n-body 模拟,但请查看 Nvidia smi 输出中的 GPU 利用率。 转到设备的 PowerShell 界面并运行 Get-HcsGpuNvidiaSmi

    下面是两个容器都运行 n-body 模拟时的示例输出:

    [10.100.10.10]: PS>Get-HcsGpuNvidiaSmi
    K8S-1HXQG13CL-1HXQG13:
    
    Fri Mar  5 13:31:16 2021
    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 460.32.03    Driver Version: 460.32.03    CUDA Version: 11.2     |
    |-------------------------------+----------------------+----------------------+
    | 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  Tesla T4            On   | 00002C74:00:00.0 Off |                    0 |
    | N/A   52C    P0    69W /  70W |    221MiB / 15109MiB |    100%      Default |
    |                               |                      |                  N/A |
    +-------------------------------+----------------------+----------------------+
    
    +-----------------------------------------------------------------------------+
    | Processes:                                                                  |
    |  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
    |        ID   ID                                                   Usage      |
    |=============================================================================|
    |    0   N/A  N/A    188342      C   /tmp/nbody                        109MiB |
    |    0   N/A  N/A    188413      C   /tmp/nbody                        109MiB |
    +-----------------------------------------------------------------------------+
    [10.100.10.10]: PS>
    

    可以看到,GPU 0 上有两个容器在 n-body 模拟下运行。 你还可以查看其相应的内存使用情况。

  4. 完成模拟后,Nvidia smi 输出会显示设备上没有正在运行的进程。

    [10.100.10.10]: PS>Get-HcsGpuNvidiaSmi
    K8S-1HXQG13CL-1HXQG13:
    
    Fri Mar  5 13:54:48 2021
    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 460.32.03    Driver Version: 460.32.03    CUDA Version: 11.2     |
    |-------------------------------+----------------------+----------------------+
    | 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  Tesla T4            On   | 00002C74:00:00.0 Off |                    0 |
    | N/A   34C    P8     9W /  70W |      0MiB / 15109MiB |      0%      Default |
    |                               |                      |                  N/A |
    +-------------------------------+----------------------+----------------------+
    
    +-----------------------------------------------------------------------------+
    | Processes:                                                                  |
    |  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
    |        ID   ID                                                   Usage      |
    |=============================================================================|
    |  No running processes found                                                 |
    +-----------------------------------------------------------------------------+
    [10.100.10.10]: PS>
    
  5. 在 n-body 模拟完成后,请查看日志以了解部署的详细信息以及完成模拟所需的时间。

    下面是第一个容器的示例输出:

    PS C:\WINDOWS\system32> kubectl -n iotedge  --kubeconfig C:\GPU-sharing\kubeconfigs\configiotuser1 logs cuda-sample1-869989578c-ssng8 cuda-sample1
    Run "nbody -benchmark [-numbodies=<numBodies>]" to measure performance.
    ==============// snipped //===================//  snipped  //=============
    > Windowed mode
    > Simulation data stored in video memory
    > Single precision floating point simulation
    > 1 Devices used for simulation
    GPU Device 0: "Turing" with compute capability 7.5
    
    > Compute 7.5 CUDA device: [Tesla T4]
    40960 bodies, total time for 10000 iterations: 170171.531 ms
    = 98.590 billion interactions per second
    = 1971.801 single-precision GFLOP/s at 20 flops per interaction
    no-op
    PS C:\WINDOWS\system32>
    

    下面是第二个容器的示例输出:

    PS C:\WINDOWS\system32> kubectl -n iotedge  --kubeconfig C:\GPU-sharing\kubeconfigs\configiotuser1 logs cuda-sample2-6db6d98689-d74kb cuda-sample2
    Run "nbody -benchmark [-numbodies=<numBodies>]" to measure performance.
    ==============// snipped //===================//  snipped  //=============
    > Windowed mode
    > Simulation data stored in video memory
    > Single precision floating point simulation
    > 1 Devices used for simulation
    GPU Device 0: "Turing" with compute capability 7.5
    
    > Compute 7.5 CUDA device: [Tesla T4]
    40960 bodies, total time for 10000 iterations: 170054.969 ms
    = 98.658 billion interactions per second
    = 1973.152 single-precision GFLOP/s at 20 flops per interaction
    no-op
    PS C:\WINDOWS\system32>
    
  6. 停止模块部署。 在设备的 IoT 中心资源中:

    1. 转到“自动设备部署”>“IoT Edge”。 选择对应于你的设备的 IoT Edge 设备。

    2. 转到“设置模块”并选择模块。

      Select Set module.

    3. 在“设置模块”选项卡上选择模块。

      Select a module.

    4. 在“模块设置”选项卡上,将“所需状态”设置为“已停止”。 选择更新

      Modify module settings.

    5. 重复上述步骤,停止在设备上部署的第二个模块。 选择“查看 + 创建”,然后选择“创建”。 这应会更新部署。

      Review and create updated deployment.

    6. 多次刷新“设置模块”页。 直到模块“运行时状态”显示为“已停止”。

      Verify deployment status.

通过上下文共享部署

现在,当 MPS 在设备上运行时,可以在两个 CUDA 容器上部署 n-body 模拟。 首先,在设备上启用 MPS。

  1. 连接到设备的 PowerShell 界面

  2. 若要在设备上启用 MPS,请运行 Start-HcsGpuMPS 命令。

    [10.100.10.10]: PS>Start-HcsGpuMPS
    K8S-1HXQG13CL-1HXQG13:
    Set compute mode to EXCLUSIVE_PROCESS for GPU 0000191E:00:00.0.
    All done.
    Created nvidia-mps.service
    [10.100.10.10]: PS>    
    
  3. 从设备的 PowerShell 接口获取 Nvidia smi 输出。 可以看到 nvidia-cuda-mps-server 进程或 MPS 服务正在设备上运行。

    下面是示例输出:

    [10.100.10.10]: PS>Get-HcsGpuNvidiaSmi
    K8S-1HXQG13CL-1HXQG13:
    
    Thu Mar  4 12:37:39 2021
    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 460.32.03    Driver Version: 460.32.03    CUDA Version: 11.2     |
    |-------------------------------+----------------------+----------------------+
    | 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  Tesla T4            On   | 00002C74:00:00.0 Off |                    0 |
    | N/A   36C    P8     9W /  70W |     28MiB / 15109MiB |      0%   E. Process |
    |                               |                      |                  N/A |
    +-------------------------------+----------------------+----------------------+
    
    +-----------------------------------------------------------------------------+
    | Processes:                                                                  |
    |  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
    |        ID   ID                                                   Usage      |
    |=============================================================================|
    |    0   N/A  N/A    122792      C   nvidia-cuda-mps-server             25MiB |
    +-----------------------------------------------------------------------------+
    [10.100.10.10]: PS>Get-HcsGpuNvidiaSmi
    
  4. 部署之前停止的模块。 通过“设置模块”将“所需状态”设置为“正在运行”。

    下面是示例输出:

    PS C:\WINDOWS\system32> kubectl get pods -n iotedge --kubeconfig C:\GPU-sharing\kubeconfigs\configiotuser1
    NAME                            READY   STATUS    RESTARTS   AGE
    cuda-sample1-869989578c-2zxh6   2/2     Running   0          44s
    cuda-sample2-6db6d98689-fn7mx   2/2     Running   0          44s
    edgeagent-79f988968b-7p2tv      2/2     Running   0          5d20h
    edgehub-d6c764847-l8v4m         2/2     Running   0          27m
    iotedged-55fdb7b5c6-l9zn8       1/1     Running   1          5d20h
    PS C:\WINDOWS\system32>
    

    可以看到,已在设备上部署并运行模块。

  5. 部署模块后,n-body 模拟也会开始在这两个容器上运行。 下面是在第一个容器上完成模拟后的示例输出:

    PS C:\WINDOWS\system32> kubectl -n iotedge logs cuda-sample1-869989578c-2zxh6 cuda-sample1
    Run "nbody -benchmark [-numbodies=<numBodies>]" to measure performance.
    ==============// snipped //===================//  snipped  //=============
    
    > Windowed mode
    > Simulation data stored in video memory
    > Single precision floating point simulation
    > 1 Devices used for simulation
    GPU Device 0: "Turing" with compute capability 7.5
    
    > Compute 7.5 CUDA device: [Tesla T4]
    40960 bodies, total time for 10000 iterations: 155256.062 ms
    = 108.062 billion interactions per second
    = 2161.232 single-precision GFLOP/s at 20 flops per interaction
    no-op
    PS C:\WINDOWS\system32> 
    

    下面是在第二个容器上完成模拟后的示例输出:

    PS C:\WINDOWS\system32> kubectl -n iotedge  --kubeconfig C:\GPU-sharing\kubeconfigs\configiotuser1 logs cuda-sample2-6db6d98689-fn7mx cuda-sample2
    Run "nbody -benchmark [-numbodies=<numBodies>]" to measure performance.
    ==============// snipped //===================//  snipped  //=============
    
    > Windowed mode
    > Simulation data stored in video memory
    > Single precision floating point simulation
    > 1 Devices used for simulation
    GPU Device 0: "Turing" with compute capability 7.5
    
    > Compute 7.5 CUDA device: [Tesla T4]
    40960 bodies, total time for 10000 iterations: 155366.359 ms
    = 107.985 billion interactions per second
    = 2159.697 single-precision GFLOP/s at 20 flops per interaction
    no-op
    PS C:\WINDOWS\system32>    
    
  6. 当两个容器都运行 n-body 模拟时,从设备的 PowerShell 接口获取 Nvidia smi 输出。 下面是示例输出。 有三个进程,nvidia-cuda-mps-server 进程(C 类型)对应于 MPS 服务,/tmp/nbody 进程(M + C 类型)对应于模块部署的 n-body 工作负载。

    [10.100.10.10]: PS>Get-HcsGpuNvidiaSmi
    K8S-1HXQG13CL-1HXQG13:
    
    Thu Mar  4 12:59:44 2021
    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 460.32.03    Driver Version: 460.32.03    CUDA Version: 11.2     |
    |-------------------------------+----------------------+----------------------+
    | 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  Tesla T4            On   | 00002C74:00:00.0 Off |                    0 |
    | N/A   54C    P0    69W /  70W |    242MiB / 15109MiB |    100%   E. Process |
    |                               |                      |                  N/A |
    +-------------------------------+----------------------+----------------------+
    
    +-----------------------------------------------------------------------------+
    | Processes:                                                                  |
    |  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
    |        ID   ID                                                   Usage      |
    |=============================================================================|
    |    0   N/A  N/A     56832    M+C   /tmp/nbody                        107MiB |
    |    0   N/A  N/A     56900    M+C   /tmp/nbody                        107MiB |
    |    0   N/A  N/A    122792      C   nvidia-cuda-mps-server             25MiB |
    +-----------------------------------------------------------------------------+
    [10.100.10.10]: PS>Get-HcsGpuNvidiaSmi
    

后续步骤