写点什么

玩转 GPU 实例 – 我的 Linux 工具箱

  • 2020-04-08
  • 本文字数:6229 字

    阅读完需:约 20 分钟

玩转GPU实例 – 我的Linux 工具箱

前言

显卡意味着什么?在不同的玩家心目中会有许多不同的答案。对我来说,开始着迷于显卡要从横空出世的 Voodoo 说起。那时候显卡市场的王者 3dfx 推出的一系列产品无论是游戏画质还是高分辨率下的流畅度都是其它产品望尘莫及的,市场的份额曾经高达 85%。只是那时候我的认识中显卡只是与游戏、视频输出效果这些场景有关,没有想到后来的所谓 GPU 居然有了今天的局面。至于后来 NVIDIA Force 的卧薪尝胆、ATI Radeon 的惊艳亮相以及 Matrox、S3 等刹那的辉煌……这些都让每一个玩家难以忘怀。



大约十年前,在饭桌上听同事说起他在读博期间参与的项目,提到了使用 CUDA 开发来以提高浮点运算的速度。那时候只是觉得所谓的高性能计算(HPC)距离我们还很远,Nvidia 的显卡用来加速运算听起来固然有趣,但更多的只是饭桌上的谈资。哪里预计得到今天的大红大紫。


至于 AWS 上的 GPU 实例最早要上溯到 2015 年。那一年发布的 EC2 G2 实例第一次为开发者提供了云计算上的 GPU 服务。四块 NVIDIA GRID GPUs 显卡提供的处理能力,让我们可以真正体会 GPU 的实力。而随着机器学习尤其是深度学习的快速发展,又进一步加速了这个领域的发展。2016 年 9 月,构建于 NVIDIA® Tesla® K80 之上的 EC2 P2 实例面世了。高达 16 块显卡的配置,不免让我们对于机器学习的发展有了更多的期望。


显然,硬件的发展还是没有及时跟上算法的进步与数据膨胀。看着明显老迈的 P2 实例难免让我心生焦虑。幸好,2017 年 10 月的 P3 实例在千呼万唤中飘然而至。8 个 NVIDIA Tesla V100 GPU、Intel Xeon E5 处理器的 64 个 vCPU、488GB RAM 以及采用 Elastic Network Adapter 技术、高达 25Gbps 的聚合网络带宽显然成为了 GPU 实例中的王者。当然仅有豪华的硬件配置是不可能解决全部的问题,还需要每个开发者充分利用好这一资源平台。在 P3 之后发布的 P3dn 以及接下来即将到来的 P4 实例,将会提供更强大的计算平台,但这都需要每个使用者的精巧构思,力求物尽其用方可尽显 GPU 的强大的能力。


去年底因为参加 NVIDIA GTC 大会的需要,又一次连接上了我的 GPU 实例,又不得不重复以往做过许多次的工作,安装、配置、编译、优化 … 这些繁琐的操作突然感觉自己在不断重复之中似乎缺少了点什么。于是心生念头,将曾经在 GPU 实例上的心得写成脚本以利于今后工作之用。这些脚本会涵盖曾经尝试过的一些内容 :


  • GPU 实例的创建与管理

  • GPU 实例的基础配置

  • 实例的系统优化

  • 实例的网络优化

  • Intel 软件的安装配置

  • OpenCV 编译安装

  • 开发工具篇

  • Nvidia 软件篇

  • Jupyter 的安装配置

  • OpenMPI 编译与配置

  • Horovod 配置

  • 深度学习框架篇(Tensorflow、PyTorch 以及 Mxnet)


在这个技术高速发展的年代,个人的努力是非常渺小的。我的这些心得与积累或有不足甚至谬误之处。非常希望听到更多的反馈与建议,也只有群智群力才能使得我们曾益其所不能。

第一部分 : GPU 实例的创建与管理

使用过 AWS 的用户都应该有过创建 EC2 实例的经验。我们常用的方法不外乎 AWS 控制台、AWS 命令行工具、CloudFormation 模版工具以及第三方的运维工具(Terraform、puppet、ansibley 以及 chef 等)。从我的经验来看,AWS 命令行工具(awscli)应该是最麻烦的一个了。原因就在于我们需要熟练的掌握的参数实在是太多了,请看完整的 awscli 中创建实例的命令 run-instance 的完整参数 :


创建实例的脚本

相信对一个普通人来说这绝对是一个不能能完成的任务。但是,事情的另一面却是 AWS 命令行工具(awscli ) 提供给我们的绝对是一个强大的、可以随心所欲进行定制的工具。用好这个工具的一个简单而有效的方法就是脚本。毫不夸张的说,一个好的脚本带给我们的价值的巨大的。它不仅可以节省我们大量的重复性的工作的时间,还可以以一种灵活的、程序化方式满足各种各样的运维的需求。而创建一个 EC2 的 GPU 实例就属于这一类的范畴。好了,我的创建实例的脚本就是这个样子的


#!/bin/bash
instance_type="p3.16xlarge"
key_name="密钥名字"
security_group_ids="安全组ID"
subnet_id="子网ID"
placement="置放群组"
block_device_mappings=""
#http://169.254.169.254/latest/user-data/
user_data="ubuntu_userdata.txt"
ebs_mapping="ebs_mapping.json"
count="数量"
region="AWS区域"
#ubuntu 18.0.4 LTS
image_id=$(aws ec2 describe-images --owners 099720109477 --filters \
'Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server*' \
'Name=state,Values=available' 'Name=architecture,Values=x86_64' --query \
'reverse(sort_by(Images, &CreationDate))[:1].ImageId' --output text --region ${region})
owner="使用者"
current_date_time="`date +%Y%m%d%H%M`";
project="项目名称"
tags="ResourceType=instance,Tags=[{Key=owner,Value=$owner},{Key=date,Value=$current_date_time},{Key=project,Value=$project}] ResourceType=volume,Tags=[{Key=owner,Value=$owner},{Key=date,Value=$current_date_time},{Key=project,Value=$project}]"
# Using --dry-run to test
INSTANCE_ID=$(aws ec2 run-instances \
--image-id ${image_id} \
--count ${count} \
--instance-type ${instance_type} \
--key-name ${key_name} \
--security-group-ids ${security_group_ids} \
--subnet-id ${subnet_id} \
--ebs-optimized --associate-public-ip-address \
--block-device-mappings "file://${ebs_mapping}" \
--user-data "file://${user_data}" \
--region ${region} \
--tag-specifications ${tags} \
--output text --query 'Instances[*].InstanceId'
)
#aws ec2 wait instance-status-ok \
aws ec2 wait instance-running \
--instance-ids ${INSTANCE_ID} --region ${region}
IP_ADDRESS=$(aws ec2 describe-instances \
--instance-ids ${INSTANCE_ID} \
--query "Reservations[*].Instances[*].PublicIpAddress" \
--region ${region} \
--output=text)
echo "The instance is availiable now, access with : ssh ubuntu@${IP_ADDRESS}."
echo "Done."
复制代码

脚本中的参数

这段脚本的内容并不复杂。理解其中的几个关键的变量就可以灵活的配置使用。其中需要提前准备几个重要的变量是-


  • 实例的类型



以 P3 实例为例,P3 实例提供了三种实例大小:带有 1 个 GPU 的 2xlarge,带有 4 个 GPU 的 p3.8xlarge 以及带有 8 个 GPU 的 p3.16xlarge。脚本中可酌情选择,例如:


instance_type=”p3.16xlarge”


  • 密钥对的名字



可以通过控制台、命令行创建。也可以将自己创建的公有密钥上传到将要使用的 AWS 区域上。关于这部分内容可以参考AWS文档,例如:


key_name=”id_rsa”


  • 安全组的ID



当我们创建实例时,以为该实例最多分配 5 个安全组。安全组是被用来控制到实例的入站数据流,以及另外一套单独规则以控制出站数据流。关于安全组的细节,请参考这里。在这里,我们的安全组设定需要开放 SSH 的端口以便于连接使用。例如:


security_group_ids=”sg-0f4bb098276d25df8″


  • 实例所属的的子网ID



子网是 VPC 内的 IP 地址范围,每个实例都要归属到一个字网当中。例如:


subnet_id=”subnet-06c44af45fcd8512f”


  • 置放群组



设置置放群组。这里提到的置放群组是放置实例的一种方式。针对深度学习,尤其是多节点分布式模型训练的场景,我们选择的是集群置放群组。这意味着,通过将一个可用区中靠近的实例打包在一起。可以实现所需的低延迟网络性能,以满足分布式模型训练通常使用的紧密耦合的节点到节点通信的要求。关于置放群组,可以通过这里了解更多。例如:


placement=”GroupName = DL-pg”


  • 块设备映射项



这里不需要使用这项设置


例如:block_device_mappings=””


上述的这些项目中,密钥对、安全组、VPC 子网以及置放群组需要预先设置好。此外,还需要了解以下几个重要的参数:


  • 用户数据



这个参数是要提供给实例的用户数据。在实例启动的时候,用户数据会被自动执行,通常用来帮助我们完善实例的构建,例如安装/升级程序包等。需要注意的是,用户数据在被执行的过程中是不能够进行与用户的交互的。在官方的文档中,并没有设计 Ubuntu 的用户数据样例。因此构建一个没有交互的自动执行的用户数据是非常关键的一步。在我的实践中,这样的一个脚本是可以很好的被实例所执行。


#!/bin/bashset -e -xexport DEBIAN_FRONTEND=noninteractiveapt-get update &&    apt-get -o Dpkg::Options::="--force-confold" upgrade -q -y --force-yes &&    apt-get -o Dpkg::Options::="--force-confold" dist-upgrade -q -y --force-yesapt-get -y autoremoveapt-get -y install awscli ec2-instance-connect git chrony screen
curl http://169.254.169.254/latest/user-data/ -o /home/ubuntu/userdata.shchmod +x /home/ubuntu/userdata.shmkdir -p /home/ubuntu/Projectschown ubuntu:ubuntu /home/ubuntu/Projectsmkdir -p /home/ubuntu/Downloadschown ubuntu:ubuntu /home/ubuntu/Downloadsecho "#---------------------¬" >> /home/ubuntu/.bashrc
复制代码


这段脚本完成的任务有 通过 apt-get update、apt-get dist-upgrade 完成的系统与软件包的升级;常用软件的安装 apt-get -y install awscli ec2-instance-connect git chrony screen;以及创建我们后续将要使用到的一些目录。我们也可以按照自己的需要进行合理的增减。要注意的一点就是不要有任何需要交互的操作,否则这个 userdate 将不会被正确的执行。另外 userdata 的大小需要控制在 16K 之内。


  • 实例数量



创建的实例的数量,这对于需要同时创建多个同样实例的场景非常用用。例如分布式训练等。例如:


count=”5″


  • AWS 区域



这里所谓的区域都是一个单独的地理区域。“区域”对于理解 AWS 的基础设施是非常重要的一个概念。如果需要更多的了解,需要参考这里。对于每一个区域都有对应的代码。例如 中国(北京)区域 的代码为 cn-north-1;中国(宁夏)区域的代码为 cn-northwest-1。

关于 Ubuntu 18.0.4

事实上,我们在使用一个 GPU 实例的时候(例如 P3 实例)会有许多个 Linux 分发版本的选择,例如 Amazon Linux 2 、Centos 以及 Ubuntu 等等。但是不得不强调的就是 NVIDA 的 CUDA 对于众多 Linux 的分发版本来说支持最好的莫过于 Ubuntu。我曾经大费周折的试图在 Debian Stretch 上为我的 GTX 1070 安装最新版本的 CUDA 。但是屡经挫折之后不得不回到了 Ubuntu 之上。按照 Canonical (Ubuntu 的开发商)的声明,Ubuntu 的下个月即将发布的 Ubuntu 20.04 LTS 将会集成 NVIDIA 私有的显卡驱动,这无疑增强了我们继续选用的信心了。


在 AWS EC2 的实例上安装 Ubuntu 18.04 不是件困难的事情。在 AWS 推荐的快速启动的操作系统清单中就提供了 Ubuntu18.04 的选项。



但是,不好的地方在于每一个操作系统的镜像(AMI)都需要有一个 AMI 的 ID。例如美国俄勒冈区域的 Ubuntu 18.04 的 64 位 X86 的 AMI ID 为 ami-0d1cd67c26f5fca19。但是不同的 AWS 区域当中的 Ubuntu 18.04 的 AMI ID 确是完全不同的。这里有一个小的技巧可以帮助我们简单的获取每个区域的 Ubuntu 18.04,只需要提供区域的代码即可。


image_id=$(aws ec2 describe-images --owners 099720109477 --filters \'Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server*' \'Name=state,Values=available' 'Name=architecture,Values=x86_64' --query \'reverse(sort_by(Images, &CreationDate))[:1].ImageId' --output text --region ${region})
复制代码


这里的关键是使用了不同 AMI 提供着的 owner 这个参数以及不同的 AMI 的描述信息。同样的方法也适用于其它的操作系统,例如 Amazon Linux 2 等。

标签(Tag)的用法

对于 AWS 资源打标签(tag)绝对是一个非常有用但很容易被忽视的地方。那么什么是“标签”呢?标签是指为 使用的 AWS 资源分配的标记。每个标签都包含我们自行定义的一个键和一个值。标签可让我们灵活的按照各种标准 (例如项目、用途、所有者) 对 AWS 资源进行分类。这在具有大量相同类型的资源时将会很有用的功能 — 可以根据分配给资源的标签快速识别特定资源。例如,您可以为不同项目的 Amazon EC2 实例定义一组标签,以跟踪不同项目实例的使用情况以及成本的状况。简单的使用方法如下:


owner="使用者名字"current_date_time="`date +%Y%m%d%H%M`";project="项目名称"tags="ResourceType=instance,Tags=[{Key=owner,Value=$owner},{Key=date,Value=$current_date_time},{Key=project,Value=$project}] ResourceType=volume,Tags=[{Key=owner,Value=$owner},{Key=date,Value=$current_date_time},{Key=project,Value=$project}]"
复制代码


这里标签的名称与标签完全是由我们自行定义的。在上面的这个例子中,就定义了实例的使用者、实例建立的日期、实例所属的项目的名称等。

网络存储(EBS)的设定

Amazon Elastic Block Store (EBS) 是 AWS 提供的一种数据块存储服务,通常与 EC2 一起使用。对于我们即将创建的实例这是一种非常适用的存储方式。设定实例中所使用的 EBS 的配置,需要在一个配置文件中声明。例如:


[{    "DeviceName": "/dev/sda1",    "Ebs": {        "DeleteOnTermination": true,        "VolumeSize": 64,        "VolumeType": "gp2",        "Encrypted": false    }}]
复制代码


在这个配置中,“DeleteOnTermination”声明了当实例终止时需要删除该存储卷;


“VolumeSize”设置的是存储容量的大小,单位是 GB;“VolumeType”需要在高性能的 io1、通用型的 gp2、吞吐量优化的 st1 以及最低成本的 sc1 四种类型中进行选择。关于这四种类型的差异可以通过这张表来一窥究竟



最后的设置项是关于数据加密。“Encrypted”用来声明存储在 EBS 上数据是否以加密方式存储。无疑,选择加密存储会很好的保护我们的隐私数据。

创建实例与连接到实例

最后的一个步骤就是利用 aws ec2 run-instances 命令在我们准备好的参数与配置项之上创建我们需要的实例。并且为了后续操作的方面,会将实例绑定 Public IP 显示出来。


IP_ADDRESS=$(aws ec2 describe-instances \
--instance-ids ${INSTANCE_ID} \
--query "Reservations[*].Instances[*].PublicIpAddress" \
--region ${region} \
--output=text)
echo "The instance is availiable now, access with : ssh ubuntu@${IP_ADDRESS}."
echo "Done."
复制代码


这样我们就可以利用 ssh 命令登陆到这台实例上面。但是,对我们而言长时间的记住一组 IP 地址显然是不切实际的。我的工作习惯是准备一组关于 EC2 使用的 Linux 的别名(在我的.bashrc 文件中定义)。通过这些别名/命令来帮助我们找到实例,甚至是帮助我们关闭或者启动实例。


alias ec2_list='aws ec2 describe-instances --output table –query '\''Reservations[*].Instances[*].[InstanceId,ImageId,State.Name,PublicIpAddress,Tags[*].Value | [0]]'\'
alias ec2_start='aws ec2 start-instances --instance-ids'
alias ec2_stop='aws ec2 stop-instances --instance-ids'
alias ec2_terminate='aws ec2 terminate-instances --instance-ids'
复制代码


只需要在命令行输入 ec2_list –region cn-northwest-1 ,就能够看到在我的账户在中国(宁夏)区域上的全部 EC2 实例,包括该实例的 Public IP。


到这里我们的 GPU 实例应该已经创建完成。接下来我们要对这台实例进行细致的优化与配置,我将在该系列的下一篇继续这项工作。


本文转载自 AWS 技术博客。


原文链接:https://amazonaws-china.com/cn/blogs/china/play-with-gpu-instances-my-linux-toolbox/


2020-04-08 15:341048

评论

发布
暂无评论
发现更多内容

精益创业者的用户体验设计

产品海豚湾

产品经理 产品设计 精益思想 用户体验 11月月更

【Go电商实战04】为什么GoFrame不支持migrate功能?我还特意去问了框架作者

王中阳Go

golang 高效工作 学习方法 程序员 11月月更

泛型由入门到精通(2)

好程序员IT教育

Java 泛型

浅析云原生

鲸品堂

4K60帧!RayLink远程控制软件如何帮助设计师远程办公?

RayLink远程工具

远程控制软件 远程办公软件 远控软件 远程桌面连接 RayLink

泛型由入门到精通(3)

好程序员IT教育

Java 泛型

从HelloWorld看Java与Kotlin

子不语Any

kotlin Andriod 11月月更

秒云加入OpenCloudOS操作系统开源社区,携手打造更智能、更可控、更可信的云原生环境

MIAOYUN

开源社区 opencloudOS

工信部电子五所李冬:在龙蜥社区的一站式自动化测试平台的探索和实践|2022云栖龙蜥实录

OpenAnolis小助手

开源 操作系统 自动化测试 龙蜥社区 2022云栖大会

mysql的高可用方案以及优缺点

想要飞的猪

2022-11-14:rust语言,请使用过程宏给结构体AAA生成结构体AAABuilder和创建AAABuilder实例的方法。 宏使用如下: #[derive(Builder)] pub stru

福大大架构师每日一题

rust 福大大 过程宏

阿里云弹性计算总经理张献涛:智能化、高效能、新交互将重塑互联网

云布道师

弹性计算 云栖大会

【愚公系列】2022年11月 微信小程序-app.json配置属性之Worker

愚公搬代码

11月月更

Thymeleaf入门教程

Studying_swz

前端 thymeleaf 11月月更

浅谈MVC、MVP、MVVM框架模式

闫同学

mvc MVP MVVM 11月月更 框架模式

从0开始,让你的Spring Boot项目跑在Linux服务器

闫同学

spring Linux 服务器 11月月更

Kotlin变量声明和类型推断

子不语Any

kotlin Andriod 11月月更

数据预处理和特征工程-特征选择-Embedded嵌入法

烧灯续昼2002

Python 机器学习 算法 sklearn 11月月更

谈谈我对服务网格的理解

阿里巴巴云原生

阿里云 云原生 服务网格

九科信息受邀参加中国总会计师协会财务数智化转型研讨会

九科Ninetech

深入浅出学习透析Nginx服务器的基本原理和配置指南「初级实践篇 」

洛神灬殇

nginx 正向代理与反向代理 11月日更 nginx 开源版 开发指南

AI音乐创作,让每一个人都成为音乐家

HarmonyOS SDK

音频 HMS Core

构建高质量的持续交付体系

老张

软件工程 持续交付

MySQL事务的隔离级别以及脏读、幻读和不可重复读

闫同学

MySQL 事务 11月月更

甩掉容量规划炸弹:用 AHPA 实现 Kubernetes 智能弹性伸缩

阿里巴巴云原生

阿里云 Kubernetes 云原生 AHPA

数字化转型有可能让所有人满意吗?

优秀

数字化转型

EMI 滤波电路是由哪些元件组成的,一文看懂!

元器件秋姐

元器件采购 元器件电商 EMI滤波电路 滤波电路 元器件知识

湖仓一体架构下的数据研发及管理

数造万象

基础逻辑门

芯动大师

Verilog 11月月更 Xilinx

分布式事务详解、理论分析、及强一致性(2PC、3PC)剖析

C++后台开发

数据库 分布式 后端开发 Linux服务器开发 C++开发

JVM Sandbox入门教程与原理浅谈

Zhendong

Java JVM

玩转GPU实例 – 我的Linux 工具箱_文化 & 方法_亚马逊云科技 (Amazon Web Services)_InfoQ精选文章