本文与VirtuSwap的Dima Zadorozhny和Fuad Babaev合作撰写。
VirtuSwap是一家初创公司,正在开发用于区块链上资产去中心化交换的创新技术。VirtuSwap的技术为那些没有直接配对的资产提供更高效的交易。缺乏直接配对导致间接交易成本高昂,意味着需要进行两次或更多次交易才能完成所需的交换,从而导致交易成本翻倍或翻三倍。VirtuSwap的基于储备的虚拟池技术通过使每笔交易直接进行解决了这个问题,节省了高达50%的交易成本。在virtuswap.io上阅读更多信息。
在本文中,我们将介绍VirtuSwap如何使用Amazon SageMaker Studio中的自定义容器功能构建强大的环境,以托管他们的GPU密集型模拟程序来解决线性优化问题。
挑战
VirtuSwap Minerva引擎根据多个参数(如交易量、当前市场流动性和交易资产的波动性)创建了最佳流动性在不同流动性池之间的分配建议,同时受到可用于分配的总流动性量的限制。为了提供这些建议,VirtuSwap Minerva使用了数千个历史交易对来模拟它们在各种流动性配置中的运行,以找到最佳的流动性分配、池费用等。
最初的实现是使用pandas数据框编程的。然而,随着模拟数据的增长,运行时间几乎增加了四倍,问题的规模也随之增加。这导致迭代变慢,几乎无法运行更大的维度任务。VirtuSwap意识到他们需要使用GPU实例来进行模拟,以获得更快的结果。
VirtuSwap需要一个与GPU兼容的类似pandas的库来运行他们的模拟,并选择了Rapids的GPU DataFrame库cuDF。cuDF用于加载、连接、聚合、过滤和操作数据等操作,具有类似pandas的API,使用CUDA实现了比pandas更快的性能。
解决方案概述
VirtuSwap选择了SageMaker Studio进行端到端开发,从笔记本中的迭代、交互式开发开始。由于SageMaker Studio的灵活性,他们决定也将其用于模拟,利用了Amazon SageMaker自定义映像的优势,这使得VirtuSwap可以引入自己需要的自定义库和软件,比如cuDF。下图说明了解决方案的工作流程。
在接下来的几节中,我们将分享构建和使用SageMaker中Rapids cuDF映像的逐步说明。
先决条件
要运行此逐步指南,您需要具有对SageMaker、Amazon Elastic Container Registry(Amazon ECR)、AWS Identity and Access Management(IAM)和AWS CodeBuild的权限的AWS帐户。此外,您还需要准备好一个SageMaker域。
创建IAM角色和策略
对于SageMaker自定义笔记本的构建过程,我们使用了AWS CloudShell,它提供了构建自定义映像所需的所有软件包。在CloudShell中,我们使用了SageMaker Docker Build,这是一个用于构建SageMaker Studio中的Docker映像的命令行界面(CLI)。该CLI可以在Amazon ECR中创建存储库,并使用CodeBuild构建容器。为此,我们需要为工具提供一个具有适当权限的IAM角色。请完成以下步骤:
-
登录AWS管理控制台并打开IAM控制台。
-
在左侧的导航窗格中,选择策略。
-
创建一个名为
sm-build-policy
的策略,具有以下权限:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "codebuild:DeleteProject", "codebuild:CreateProject", "codebuild:BatchGetBuilds", "codebuild:StartBuild" ], "Resource": "arn:aws:codebuild:*:*:project/sagemaker-studio*" }, { "Effect": "Allow", "Action": "logs:CreateLogStream", "Resource": "arn:aws:logs:*:*:log-group:/aws/codebuild/sagemaker-studio*" }, { "Effect": "Allow", "Action": [ "logs:GetLogEvents", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:log-group:/aws/codebuild/sagemaker-studio*:log-stream:*" }, { "Effect": "Allow", "Action": "logs:CreateLogGroup", "Resource": "*" }, { "Effect": "Allow", "Action": [ "ecr:CreateRepository", "ecr:BatchGetImage", "ecr:CompleteLayerUpload", "ecr:DescribeImages", "ecr:DescribeRepositories", "ecr:UploadLayerPart", "ecr:ListImages", "ecr:InitiateLayerUpload", "ecr:BatchCheckLayerAvailability", "ecr:PutImage" ], "Resource": "arn:aws:ecr:*:*:repository/sagemaker-studio*" }, { "Sid": "ReadAccessToPrebuiltAwsImages", "Effect": "Allow", "Action": [ "ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer" ], "Resource": [ "arn:aws:ecr:*:763104351884:repository/*", "arn:aws:ecr:*:217643126080:repository/*", "arn:aws:ecr:*:727897471807:repository/*", "arn:aws:ecr:*:626614931356:repository/*", "arn:aws:ecr:*:683313688378:repository/*", "arn:aws:ecr:*:520713654638:repository/*", "arn:aws:ecr:*:462105765813:repository/*" ] }, { "Sid": "EcrAuthorizationTokenRetrieval", "Effect": "Allow", "Action": [ "ecr:GetAuthorizationToken" ], "Resource": [ "*" ] }, { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:DeleteObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::sagemaker-*/*" }, { "Effect": "Allow", "Action": [ "s3:CreateBucket" ], "Resource": "arn:aws:s3:::sagemaker*" }, { "Effect": "Allow", "Action": [ "iam:GetRole", "iam:ListRoles" ], "Resource": "*" }, { "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::*:role/*", "Condition": { "StringLikeIfExists": { "iam:PassedToService": "codebuild.amazonaws.com" } } }, { "Effect": "Allow", "Action": [ "ecr:CreateRepository", "ecr:BatchGetImage", "ecr:CompleteLayerUpload", "ecr:DescribeImages", "ecr:DescribeRepositories", "ecr:UploadLayerPart", "ecr:ListImages", "ecr:InitiateLayerUpload", "ecr:BatchCheckLayerAvailability", "ecr:PutImage" ], "Resource": "arn:aws:ecr:*:*:repository/*" } ] }
权限提供了完全利用实用程序的能力:创建存储库、创建CodeBuild作业、使用Amazon Simple Storage Service(Amazon S3)和将日志发送到Amazon CloudWatch。
-
创建名为
sm-build-role
的角色,并添加以下信任策略,并添加之前创建的策略sm-build-policy
:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "codebuild.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
现在,让我们回顾一下CloudShell中的步骤。
在CloudShell中创建cuDF Docker镜像
为了我们的目的,我们需要一个Rapids CUDA镜像,该镜像还包括一个ipykernel,以便可以在SageMaker Studio笔记本中使用该镜像。
我们使用RapidsAI在官方Rapids AI Docker Hub中提供的现有CUDA镜像,并添加了ipykernel
安装。
在CloudShell终端中运行以下命令:
printf "FROM nvcr.io/nvidia/rapidsai/rapidsai:0.16-cuda10.1-base-ubuntu18.04
RUN pip install ipykernel && \
python -m ipykernel install --sys-prefix && \
useradd --create-home --shell /bin/bash --gid 100 --uid 1000 sagemaker-user
USER sagemaker-user" > Dockerfile
这将创建用于构建我们的SageMaker自定义Docker镜像的Dockerfile。
构建并将镜像推送到存储库
如上所述,我们使用了SageMaker Docker Build库,该库允许数据科学家和开发人员轻松构建自定义容器镜像。有关更多信息,请参阅使用Amazon SageMaker Studio Image Build CLI从您的Studio笔记本构建容器镜像。
以下命令将创建一个ECR存储库(如果存储库不存在)。 sm-docker将创建它,并构建并推送新的Docker镜像到创建的存储库:
sm-docker build . --repository rapids:v1 --role sm-build-role
如果您的CloudShell中缺少sm-docker
,请运行以下代码:
pip3 install sagemaker-studio-image-build
完成后,将返回ECR镜像URI。
创建SageMaker自定义镜像
在创建自定义Docker镜像并将其推送到容器存储库(Amazon ECR)之后,您可以配置SageMaker以使用该自定义Docker镜像。完成以下步骤:
- 在SageMaker控制台中,选择导航窗格中的Images。
- 选择Create image。
- 输入上一节中的镜像URI输出,然后选择Next。
- 对于Image name和Image display name,输入
rapids
。 - 对于Description,输入描述。
- 对于IAM role,选择适合您SageMaker域的适当IAM角色。
- 对于EFS mount path,输入
/home/sagemaker-user
(默认)。 - 展开Advanced configuration。
- 对于User ID,输入
1000
。 - 对于Group ID,输入
100
。
- 在图像类型部分,选择SageMaker Studio 图像。
- 选择添加内核。
- 对于内核名称,输入
conda-env-rapids-py
。 - 对于内核显示名称,输入
rapids
。 - 选择提交以创建 SageMaker 图像。
将新图像附加到 SageMaker Studio 域
现在您已经创建了自定义图像,您需要将其附加到您的域中以供使用。请完成以下步骤:
- 在 SageMaker 控制台上,选择导航窗格中的域。
- 选择您的域。此步骤是可选的;您可以直接在域中创建和附加自定义图像,跳过此步骤。
- 在域详细信息页面上,选择环境选项卡,然后选择附加图像。
- 选择现有图像,然后从列表中选择新图像(
rapids
)。 - 选择下一步。
- 查看自定义图像配置,并确保将图像类型设置为SageMaker Studio 图像,与上一步中的内核名称和内核显示名称相同。
- 选择提交。
自定义图像现在在 SageMaker Studio 中可用,并准备好使用。
使用图像创建新笔记本
有关启动新笔记本的说明,请参阅在 Amazon SageMaker Studio 中启动自定义 SageMaker 图像。请完成以下步骤:
- 在 SageMaker Studio 控制台上,选择打开启动器。
- 选择更改环境。
- 对于图像,选择新创建的图像,
rapids v1
。 - 对于内核,选择
rapids
。 - 对于实例类型,选择您的实例。
SageMaker Studio 提供了从 AWS 加速计算、通用计算、计算优化或内存优化系列中选择实例的选项。这种灵活性允许您在 CPU 和 GPU 之间无缝切换,并根据需要动态调整实例大小。对于我们的笔记本,我们使用了 ml.g4dn.2xlarge 实例类型,在利用 GPU 加速器时测试 cuDF 的性能。
- 选择选择。
- 选择您的环境并选择创建笔记本,然后等待笔记本内核准备就绪。
验证自定义镜像
为了验证您的自定义镜像是否已启动并准备好使用 cuDF,请创建一个新单元格,输入import cudf
,然后运行它。
清理
通过选择运行终端和内核并关闭正在运行的实例,关闭在 SageMaker Studio 中运行的测试笔记本的 Jupyter 实例。
运行时间比较结果
我们在 SageMaker g4dn.2xlarge 实例上使用 CPU 和 GPU 对我们的代码进行了运行时间比较,时间复杂度为 O(N)。如下图所示的结果显示了使用 GPU 相对于使用 CPU 的效率。
GPU 的主要优势在于其能够进行并行处理。当我们增加 N 的值时,CPU 上的运行时间以 3N 的速率增加。另一方面,使用 GPU,增加的速率可以描述为 2N,如上图所示。问题规模越大,GPU 的效率就越高。在我们的案例中,使用 GPU 至少比使用 CPU 快 20 倍。这突显了在现代计算中,尤其是对于需要快速处理大量数据的任务而言,GPU 的不断增长的重要性。
借助 SageMaker GPU 实例,VirtuSwap 能够显著增加已解决问题的维度并更快地找到解决方案。
结论
在本文中,我们展示了 VirtuSwap 如何通过使用自定义镜像来定制 SageMaker Studio 来解决一个复杂的问题。通过能够轻松更改运行环境并在不同的实例、大小和内核之间切换,VirtuSwap 能够快速进行实验,并将运行时间加快了 15 倍,提供了可扩展的解决方案。
作为下一步,VirtuSwap 正考虑扩大他们对 SageMaker 的使用,并在 Amazon SageMaker 处理中运行他们从各种区块链收集到的大量数据。