写点什么

玩转 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:341340

评论

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

你以为在做的是微服务?不!你只是做了个比单体还糟糕的分布式单体!

程序猿DD

微服务

你的终端从未如此优雅

Kareza

终端工具 3月日更 Hyper

如何成为一名架构师?

xcbeyond

程序人生 方法论 架构师 成长与思考 3月日更

带你了解VXLAN网络中报文的转发机制

华为云开发者联盟

网络 网关 VXLAN 报文 分布式网关

安卓应用程序开发理论!免费Android高级工程师学习资源,附面试题答案

欢喜学安卓

android 程序员 面试 移动开发

细粒度授权在安全领域的重要性

龙归科技

安全 iam 细粒度 ABAC PBAC

区块链应用解决方案赋能到农产品溯源上究竟能解决什么问题?

源中瑞-龙先生

一步一步教你如何在Centos7中配置Kafka运行时环境

happlyfox

28天写作 3月日更

硬核!一文学完Flink流计算常用算子(Flink算子大全)

五分钟学大数据

大数据 flink 28天写作 3月日更

华云大咖说 | 华云数据与瀚高软件携手共建国产云生态 助力政企用户安全可靠发展

华云数据

物联网常用协议:MQTT、CoAP、LwM2M、HTTP、LoRaWAN和NB-IoT

不脱发的程序猿

物联网 通信协议 28天写作 3月日更 物联网常用协议

【LeetCode】验证二叉树的前序序列化Java题解

Albert

算法 LeetCode 28天写作 3月日更

植树节,种个二叉树吧?

悟空聊架构

数据结构 算法 二叉树

《未来世界的幸存者》读书笔记

SilentMacUser

极客时间 互联网 技术学习 阅读 阮一峰

寻找被遗忘的勇气(十二)

Changing Lin

3月日更

数字孪生技术如何实现复制世界?关键的关键是…

华为云开发者联盟

数据中心 数字孪生 节能 仿真 数据中心网图服务

你的终端从未如此高效

Kareza

3月日更 Oh My Zsh

真·“拜师学艺”?2021中科院开源之夏,开源大牛1V1&万元奖金只等你来!

京东科技开发者

开源 开源社区

聊聊什么是CommonJs和Es Module及它们的区别

蛙人

大前端 js ES6

“新作者 新入驻 新征程”第一季获奖名单

InfoQ写作社区官方

热门活动

安卓系统开发架构!5214页PDF的进阶架构师学习笔记,成功入职腾讯

欢喜学安卓

android 程序员 面试 移动开发

知道Python中的字符串是什么吗?

华为云开发者联盟

Python 编程语言 字符串 字符

一起来学习LiteOS中断模块的源代码

华为云开发者联盟

代码 华为云 LiteOS 中断 中断控制器

力扣(LeetCode)刷题,简单题(第27期)

不脱发的程序猿

面试 LeetCode 28天写作 算法面经 3月日更

谷歌大脑团队官方推荐,用浏览器实现深度学习的「黑科技」教程来了!

图灵社区

JavaScript 人工智能 机器学习 深度学习 大前端

融云集成之避坑指南-Android推送篇

融云 RongCloud

音视频

关于广东欢太科技可不可信?那是你还不了解

Geek_4a453c

企业 欢太 欢太科技

2月大事件:度目CM-Mini智能面板机全新发布,飞桨PaddleGAN“复活”李焕英

百度大脑

百度 百度大脑

对标阿里P9Java架构师面试题,已助我拿下字节、蚂蚁、滴滴三家Offer

Java架构追梦

Java 阿里巴巴 架构 面试 滴滴

技术债是什么、怎么还?你想知道的都在这一篇文章里了!

禅道项目管理

技术 技术债 问题

与前端训练营的日子 -- Week19

SamGo

学习

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