数据中心/云端

使用 NVIDIA CUDA-X 和 Coiled 简化云端环境设置并加速数据科学运算

想象一下,分析纽约市数百万次的拼车旅程 — — 跟踪各自治市的模式、比较服务定价或确定有利可图的取车地点。公开发布的 New York City Taxi and Limousine Commission (TLC) 行程记录数据包含有价值的信息,可以揭示具有划时代意义的见解,但由于数据量庞大,分析师需要等待数小时才能得出结果。

这些延迟会中断分析流程并限制业务响应能力。出租车公司、城市规划部门和金融公司的数据科学家需要及时获得见解,以便做出关键决策。等待 9 分钟与 5 秒之间的区别不仅在于方便,还在于竞争优势。

现代数据科学非常适合 GPU 并行。过滤和转换大型数据集等操作需要在数百万个独立数据点中应用相同的功能。在处理 NYC 拼车数据集时,GPU 可以同时评估数千次拼车的计算,而不是按顺序进行,从而大幅缩短计算时间。

尽管具有这些优势,但获取 GPU 的强大功能通常需要专门的编程模型和复杂的云配置。最近的发展使得任何具备基本 Python 技能的人都可以使用 GPU 加速的数据科学,从而无需专门的硬件投资。

本文将介绍如何将 NVIDIA RAPIDS (NVIDIA CUDA-X 库的一部分) 和云 GPU 与云平台 Coiled 结合使用,该平台旨在简化大规模运行 Python 工作负载的过程。

预备知识

NVIDIA RAPIDS:GPU 加速适用于 PyData 生态系统

NVIDIA RAPIDS 为数据科学工作负载提供 GPU 加速,无需更改代码。cudf.pandas 加速器支持 GPU 即时执行 pandas 运算:

%load_ext cudf.pandas
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

详细了解 NVIDIA cuDF 如何将 pandas 加速高达 150 倍。

云 GPU 

许多云平台支持即时访问最新的 NVIDIA GPU 架构,无需硬件刷新周期,可根据计算需求灵活扩展资源。这种可用性为各种规模的团队普及了先进的 GPU 加速。

这些先进 GPU 的性能优势改变了数据分析能力。借助 NYC 拼车数据集,以前在 CPU 上花费几分钟的操作现在只需几秒钟即可完成,从而实现从根本上改变分析工作流程的迭代探索。数据科学家可以测试更多假设,探索更多变量,并通过近乎即时的反馈完善模型,从而获得更深入的见解和发现,否则这些见解和发现可能会被隐藏起来。

虽然云环境通常涉及配置挑战,但 Coiled 等专用平台可以简化 GPU 工作流的此过程。通过抽象化资源配置和环境设置,这些解决方案使数据科学家能够专注于分析而不是基础设施管理,通过消除高级计算能力的技术障碍来加速创新。

连续笔记本 

使用以下命令启动交互式 Jupyter notebook 会话: 连续笔记本 然后,通过 notebook 服务运行 RAPIDS notebook 容器。

coiled notebook start --gpu --container nvcr.io/nvidia/rapidsai/notebooks:25.02-cuda12.8-py3.12

请注意,--gpu 标志将自动选择搭载 NVIDIA T4 GPU 的 g4dn.xlarge 实例。您可以添加 --vm-type 标志,以明确选择具有不同 GPU 配置的其他机器类型。例如,要选择配备四个 L4 GPU 的计算机,您需要运行以下命令。

coiled notebook start --gpu --vm-type g6.24xlarge --container nvcr.io/nvidia/rapidsai/notebooks:25.02-cuda12.8-py3.12

要访问 Jupyter,请单击终端中显示的链接。

This image displays a screenshot of a terminal where the link to the Jupyterlab deployment along with approximate cost is displayed after running Coiled notebook start.
图 1。在 Coiled 上启动 Notebook 会话后输出
This image displays a Jupyterlab screenshot on a web browser where nvidia-smi is run to show that it has access to a GPU.
图 2。支持 GPU 访问的 JupyterLab,通过 Coiled 推出

如上面的代码片段所示,从本地开发过渡到云 GPU 执行是无缝的,并且使用 RAPIDS Notebook 镜像提供了一种加速工作流程的便捷方法,从根本上改变了处理大规模问题的方式。

连续运行 

您还可以通过 Coiled Run 在临时 VM 中运行 Python 脚本。此操作会从云端启动 VM,使用 package sync 从本地环境复制所有必要的软件包,运行脚本并关闭 VM。

coiled run python my_code.py  # Boots a VM on the cloud, runs the scripts, then shuts down again

使用 RAPIDS 容器在远程环境中运行 GPU 代码。您可以将 coiled CLI 设置为在执行完成后将 VM 保留几分钟,以防您想再次运行它并重复使用相同的硬件。

$ coiled run --gpu --name rapids-demo --keepalive 5m --container nvcr.io/nvidia/rapidsai/base:25.02-cuda12.8-py3.12

与 cudf.pandas CLI 工具搭配使用时,效果非常好

$ coiled run --gpu --name rapids-demo --keepalive 5m --container nvcr.io/nvidia/rapidsai/base:25.02-cuda12.8-py3.12 -- python -m cudf.pandas cudf_pandas_coiled_demo.py

Output
------

This container image and its contents are governed by the NVIDIA Deep Learning Container License.
By pulling and using the container, you accept the terms and conditions of this license:
https://developer.download.nvidia.com/licenses/NVIDIA_Deep_Learning_Container_License.pdf

Calculate violations by state took: 3.470 seconds
Calculate violations by vehicle type took: 0.145 seconds
Calculate violations by day of week took: 1.238 seconds

在 NVIDIA RAPIDS 部署文档中,您将找到本实验中使用的 Jupyter Notebook 。您可以下载并运行它,以重现本文中提到的性能数字。

分析 ride-share 数据集

纽约市 TLC 行程记录数据 可通过 S3 获取。此数据也可以在 Coiled 的 S3 存储桶 (用于本示例) 上以 parquet 格式提供,并被划分为 100 MB 的文件。

我使用了 60 个分区,对应最新记录的数据,并转换为大约 64.8M 行数据。通过对这些数据执行不同的运算,可以了解使用 cudf.pandas 加速器与 vanilla Pandas 相比所实现的加速。

我使用了 g6.24xlarge EC2 实例,如上一部分中的代码片段所示。这台机器配备四个 NVIDIA L4 Tensor Core GPU、96 个 vCPU 和 384 GB 内存。

以下展示了无需更改代码即可加速的一些可能操作。

加载数据并优化数据类型

从 S3 加载数据需结合使用 s3fs 和 Pandas 上的 read_parquet() 函数。

import pandas as pd
path_files = []

for i in range(660,720):
    path_files.append(pd.read_parquet(f"s3://coiled-data/uber/part.{i}.parquet", filesystem=fs))

data = pd.concat(path_files, ignore_index=True)

为了优化内存使用,我将所有字符串和对象类型转换为分类值,并分别将 int32 和 float64 转换为 int16 和 float32。

# Convert data types to save memory
for col in data.columns:
    if data[col].dtype == 'int32':
        if data[col].min() >= -32768 and data[col].max() <= 32767:
            data[col] = data[col].astype('int16')
    if data[col].dtype == 'float64':
        data[col] = data[col].astype('float32')
    if data[col].dtype == 'string' or data[col].dtype == 'object':
        data[col] = data[col].astype('category')

使用 Pandas 时,此操作需要 15 秒,但使用 cudf.pandas 加速器时,仅需 1 秒。

按公司查找每月收入和利润

接下来,我想了解数据中每个唯一月份各共享出行公司的收入和利润。该数据集包含关于乘客支付的车费的几列,包括基本乘客车费、过路费和销售税。* 为了计算公司的总收入,我汇总了与乘客支付的车费相关的所有列,并将其存储在名为 total_fare 的列中。然后,我逐组执行操作,按公司和月份对这些数据进行分组。

data['pickup_month'] = data['pickup_datetime'].dt.month

data['total_fare'] = data['base_passenger_fare'] + data['tolls'] + data['bcf'] + data['sales_tax'] + data['congestion_surcharge'] + data['airport_fee']

grouped = data.groupby(['company', 'pickup_month']).agg({
    'company': 'count',
    'total_fare': ['sum', 'mean'],
    'driver_pay': 'sum',
    'tips': 'sum'
}).reset_index()

grouped.columns = ['company', 'pickup_month', 'trip_count', 'total_revenue', 'avg_fare', 'total_driver_pay', 'total_tips']

grouped['total_driver_payout'] = grouped['total_driver_pay'] + grouped['total_tips']

grouped = grouped[['company', 'pickup_month', 'trip_count', 'total_revenue', 'avg_fare', 'total_driver_payout']]

grouped = grouped.sort_values(['company', 'pickup_month'])

grouped['profit'] = grouped['total_revenue'] - grouped['total_driver_payout']

grouped.head()

在 Pandas 上,此操作大约需要 4.7 秒,但启用 cudf.pandas 加速器后,仅需 2.67 秒即可完成。

根据持续时间对路线进行分类

为了了解用户定义函数 (User-Defined Functions, UDF) 中的加速情况,我将数据中的所有行程分为以下三类:

  1. 短程 (在 trip_category 列中用 0 表示) 表示行程少于 10 分钟。
  2. 中度 (在 trip_category 列中用 1 表示) 表示 10 到 20 分钟的行程。
  3. 长途 (在 trip_category 列中用 2 表示) ,适用于 20 分钟以上的行程。

然后,我使用这些类别来计算每个类别中的平均车费和出行次数。

def categorize_trip(row):
    if row['trip_time'] < 600:  # Less than 10 minutes
        return 0
    elif row['trip_time'] < 1200:  # 10-20 minutes
        return 1
    else:  # More than 20 minutes
        return 2

# Apply UDF
data['trip_category'] = data.apply(categorize_trip, axis=1)

# Create a mapping for trip categories
trip_category_map = {0: 'short', 1: 'medium', 2: 'long'}

# Group by trip category
category_stats = data.groupby('trip_category').agg({
    'total_fare': ['mean', 'sum'],
    'trip_time': 'count'
})

# Rename the index with descriptive labels
category_stats.index = category_stats.index.map(lambda x: f"{trip_category_map[x]}")

category_stats

在 Pandas 上执行此操作需要 408 秒,但启用 cudf.pandas 加速器后,只需 0.2 秒即可完成。这是因为需要对数据集中的每一行应用 categorize_trip 函数,但该函数本质上是一项可并行的任务,因此利用 GPU 可显著提高性能。

查找常用路线

TLC 数据集包含列 PULocationID 和 DOLocationID,根据 NYC TLC 的出租车区域表示区域和自治市信息。您可以在以下位置找到信息并查找与索引对应的区域: CSV 格式

现在,我们可以将此数据集合并到 trips 数据帧中,找出十大常用路线。

taxi_zones = pd.read_csv('taxi_zones.csv', usecols=['LocationID', 'zone', 'borough'])

#Convert PULocationID to pickup_location combining zone and borough information
data = pd.merge(data, taxi_zones, left_on='PULocationID', right_on='LocationID', how='left')
for col in ['zone', 'borough']:
    data[col] = data[col].fillna('NA')
data['pickup_location'] = data['zone'] + ',' + data['borough']
data.drop(['LocationID', 'zone', 'borough'], axis=1, inplace=True)

#Doing the same for dropoff location

location_group = data.groupby(['pickup_location', 'dropoff_location']).size().reset_index(name='ride_count')
location_group = location_group.sort_values('ride_count', ascending=False)

# Identify top 10 hotspots
top_hotspots = location_group.head(10)
print("Top 10 Pickup and Dropoff Hotspots:")
print(top_hotspots)

在 Pandas 上,每个合并操作大约需要 30 秒,但使用 cudf.pandas 加速器只需 1.3 秒。

总体时间比较 

我们来比较一下整个示例 Notebook 的运行时间 。在 CPU 上执行标准 Pandas 需要 18 分钟 45 秒。相比之下,使用 cudf.pandas 的 GPU 加速版本仅在 2 分钟 6 秒内执行了相同的操作,仅执行时间就提高了 8.9 倍。

考虑到基础设施设置开销 (在 Coiled 上使用 RAPIDS Docker 镜像置备配备 GPU 的 EC2 实例需要 2 分钟 45 秒) ,总运行时间为 4 分钟 50 秒。与基于 CPU 的实施方案相比,这仍然代表着性能提升了 3.9 倍,只需很少的基础设施设置即可实现。

这些指标清楚地表明,GPU 加速为涉及大数据的计算密集型操作带来了巨大优势,尤其是涉及元素级转换和用户定义函数的操作。

总结 

通过利用 cudf.pandas,我们实现了显著的性能提升,从整体加速的 8.9 倍提升到 UDF 操作的 30 倍,并且无需更改代码。Coiled 的平台通过自动调配和自动扩展资源降低了 GPU 的云计算复杂性,通过在使用后关闭来确保资源设置的简单性和成本效益。熟悉的语法与简化的基础架构管理相结合,为数据科学家创建了一个强大的工具包,以加速分析工作流程、缩短开发周期,并从大型数据集中提取更多价值,同时保持对见解而非基础架构的关注。

了解详情:

  1. 开始使用 RAPIDS
  2. 安装 盘管
  3. cudf.pandas 的 API 参考

 

标签