写点什么

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

  • 2020 年 4 月 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 年 4 月 08 日 15:34568

评论

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

双非本科电子跨专业,苦学八个月,投岗阿里/滴滴后端三面,最终拿下offer

今晚早点睡

Java 阿里巴巴 面试 计算机

运维必经操作,TcaplusDB tcapsvr扩缩容介绍

数据人er

数据库 nosql tencentdb TcaplusDB

极狐 GitLab 探秘系列|极狐 GitLab 初探(下)

极狐GitLab

DevOps DevSecOps gitops

TimeUtils 实用封装

Changing Lin

8月日更

IT公司防止运维偷窥和篡改数据库的最佳武器-云堡垒机!

行云管家

数据安全 堡垒机 数据泄露

从错误中成长

escray

学习 极客时间 朱赟的技术管理课 8月日更

Java开发三年月薪才12K,你知道如何用面向对象思想写好并发编程吗?

策划Java工程师

Java 程序员 后端

Java开发从零开始!《SpringCloud超级入门(4)

策划Java工程师

Java 程序员 后端

Java开发入门教程!程序员:面试官

策划Java工程师

Java 程序员 后端

Java开发基础不牢?什么是中间件?

策划Java工程师

Java 程序员 后端

终于彻底搞清楚了 MySQL spin-lock 之一次CPU问题定位过程总结

互联网架构师小马

Java开发前景怎么样?【Spring Boot 21

策划Java工程师

Java 程序员 后端

架构实战营毕业总结

eoeoeo

架构实战营

Java开发6年了,BAT面试文档:ActiveMQ(1)

策划Java工程师

Java 程序员 后端

Java开发全套学习!MySQL进阶,秒变大神(1)

策划Java工程师

Java 程序员 后端

终于有人把操作系统,网络系统,线程进程,IO模型全部总结出来了

程序员 架构 面试 操作系统 计算机

区块链的兴起及其司法运用

CECBC

博睿数据App 3.0四大新功能来袭,大幅提升App用户体验可见性

博睿数据

毕业总结

Vincent

架构训练营

TCL携大屏天团领跑UDE,斩获多项创新大奖

科技热闻

Java开发快速学习!三面蚂蚁金服成功拿到offer后,他说他累了

策划Java工程师

Java 程序员 后端

亏损、退市、卖身...区块链如何挽救影视行业?

CECBC

应届生怎么走Linux下C++后台服务器开发路线,工作3-5年的知识体系

Linux服务器开发

Linux C/C++ linux开发 Linux服务器开发 Linux后台开发

币安链NFT游戏系统开发区块链技术

薇電13242772558

区块链 智能合约

京东:Flink SQL 优化实战

Apache Flink

flink

Java开发基础面试题,【springcloud

策划Java工程师

Java 程序员 后端

人工智能从业者需要掌握哪些数学知识

小术晓术

人工智能 数学

全国首笔“区块链+闲置住宅”交易在昆山完成

CECBC

架构实战营模块3作业指导

华仔

架构实战营

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