当 Mars 遇上 RAPIDS:用 GPU 以并行的方式加速数据科学

背景

在数据科学世界,Python 是一个不可忽视的存在,且有愈演愈烈之势。而其中主要的使用工具,包括 Numpy、Pandas 和 Scikit-learn 等。

Numpy

Numpy 是数值计算的基础包,内部提供了多维数组(ndarray)这样一个数据结构,用户可以很方便地在任意维度上进行数值计算。

image

我们举一个蒙特卡洛方法求解 Pi 的例子。这背后的原理非常简单,现在我们有个半径为1的圆和边长为2的正方形,他们的中心都在原点。现在我们生成大量的均匀分布的点,让这些点落在正方形内,通过简单的推导,我们就可以知道,Pi 的值 = 落在圆内的点的个数 / 点的总数 * 4。

这里要注意,就是随机生成的点的个数越多,结果越精确。

用 Numpy 实现如下:

import numpy as npN = 10 ** 7  # 1千万个点data = np.random.uniform(-1, 1, size=(N, 2))  # 生成1千万个x轴和y轴都介于-1和1间的点
inside = (np.sqrt((data ** 2).sum(axis=1)) < 1).sum()  # 计算到原点的距离小于1的点的个数
pi = 4 * inside / N
print('pi: %.5f' % pi)

可以看到,用 Numpy 来进行数值计算非常简单,只要寥寥数行代码,而如果读者习惯了 Numpy 这种面相数组的思维方式之后,无论是代码的可读性还是执行效率都会有巨大提升。

pandas

pandas 是一个强大的数据分析和处理的工具,它其中包含了海量的 API 来帮助用户在二维数据(DataFrame)上进行分析和处理。

pandas 中的一个核心数据结构就是 DataFrame,它可以简单理解成表数据,但不同的是,它在行和列上都包含索引(Index),要注意这里不同于数据库的索引的概念,它的索引可以这么理解:当从行看 DataFrame 时,我们可以把 DataFrame 看成行索引到行数据的这么一个字典,通过行索引,可以很方便地选中一行数据;列也同理。

我们拿 movielens 的数据集 作为简单的例子,来看 pandas 是如何使用的。这里我们用的是 Movielens 20M Dataset.

import pandas as pdratings = pd.read_csv('ml-20m/ratings.csv')
ratings.groupby('userId').agg({'rating': ['sum', 'mean', 'max', 'min']})

通过一行简单的 pandas.read_csv 就可以读取 CSV 数据,接着按 userId 做分组聚合,求 rating 这列在每组的总和、平均、最大、最小值。

“食用“ pandas 的最佳方式,还是在 Jupyter notebook 里,以交互式的方式来分析数据,这种体验会让你不由感叹:人生苦短,我用 xx(😉)

scikit-learn

scikit-learn 是一个 Python 机器学习包,提供了大量机器学习算法,用户不需要知道算法的细节,只要通过几个简单的 high-level 接口就可以完成机器学习任务。当然现在很多算法都使用深度学习,但 scikit-learn 依然能作为基础机器学习库来串联整个流程。

我们以 K-最邻近算法为例,来看看用 scikit-learn 如何完成这个任务。

import pandas as pd
from sklearn.neighbors import NearestNeighborsdf = pd.read_csv('data.csv')  # 输入是 CSV 文件,包含 20万个向量,每个向量10个元素
nn = NearestNeighbors(n_neighbors=10)
nn.fit(df)
neighbors = nn.kneighbors(df)

fit接口就是 scikit-learn 里最常用的用来学习的接口。可以看到整个过程非常简单易懂。

Mars——Numpy、pandas 和 scikit-learn 的并行和分布式加速器

Python 数据科学栈非常强大,但它们有如下几个问题:

  1. 现在是多核时代,这几个库里鲜有操作能利用得上多核的能力。
  2. 随着深度学习的流行,用来加速数据科学的新的硬件层出不穷,这其中最常见的就是 GPU,在深度学习前序流程中进行数据处理,我们是不是也能用上 GPU 来加速呢?
  3. 这几个库的操作都是命令式的(imperative),和命令式相对应的就是声明式(declarative)。命令式的更关心 how to do,每一个操作都会立即得到结果,方便对结果进行探索,优点是很灵活;缺点则是中间过程可能占用大量内存,不能及时释放,而且每个操作之间就被割裂了,没有办法做算子融合来提升性能;那相对应的声明式就刚好相反,它更关心 what to do,它只关心结果是什么,中间怎么做并没有这么关心,典型的声明式像 SQL、TensorFlow 1.x,声明式可以等用户真正需要结果的时候才去执行,也就是 lazy evaluation,这中间过程就可以做大量的优化,因此性能上也会有更好的表现,缺点自然也就是命令式的优点,它不够灵活,调试起来比较困难。

为了解决这几个问题,Mars 被我们开发出来,Mars 在 MaxCompute 团队内部诞生,它的主要目标就是让 Numpy、pandas 和 scikit-learn 等数据科学的库能够并行和分布式执行,充分利用多核和新的硬件。

Mars 的开发过程中,我们核心关注的几点包括:

  1. 我们希望 Mars 足够简单,只要会用 Numpy、pandas 或 scikit-learn 就会用 Mars。
  2. 避免重复造轮子,我们希望能利用到这些库已有的成果,只需要能让他们被调度到多核/多机上即可。
  3. 声明式和命令式兼得,用户可以在这两者之间自由选择,灵活度和性能兼而有之。
  4. 足够健壮,生产可用,能应付各种 failover 的情况。

当然这些是我们的目标,也是我们一直努力的方向。

Mars tensor:Numpy 的并行和分布式加速器

上面说过,我们的目标之一是,只要会用 Numpy 等数据科学包,就会用 Mars。我们直接来看代码,还是以蒙特卡洛为例。变成 Mars 的代码是什么样子呢?

import mars.tensor as mtN = 10 ** 10data = mt.random.uniform(-1, 1, size=(N, 2))
inside = (mt.sqrt((data ** 2).sum(axis=1)) < 1).sum()
pi = (4 * inside / N).execute()
print('pi: %.5f' % pi)

可以看到,区别就只有两处:import numpy as np 变成 import mars.tensor as mt ,后续的 np. 都变成 mt. ;pi 在打印之前调用了一下 .execute() 方法。

也就是默认情况下,Mars 会按照声明式的方式,代码本身移植的代价极低,而在真正需要一个数据的时候,通过 .execute() 去触发执行。这样能最大限度得优化性能,以及减少中间过程内存消耗。

这里,我们还将数据的规模扩大了 1000 倍,来到了 100 亿个点。之前 1/1000 的数据量的时候,在我的笔记本上需要 757ms;而现在数据扩大一千倍,光 data 就需要 150G 的内存,这用 Numpy 本身根本无法完成。而使用 Mars,计算时间只需要 3min 44s,而峰值内存只需要 1G 左右。假设我们认为内存无限大,Numpy 需要的时间也就是之前的 1000 倍,大概是 12min 多,可以看到 Mars 充分利用了多核的能力,并且通过声明式的方式,极大减少了中间内存占用。

前面说到,我们试图让声明式和命令式兼得,而使用命令式的风格,只需要在代码的开始配置一个选项即可。

import mars.tensor as mt
from mars.config import optionsoptions.eager_mode = True  # 打开 eager mode 后,每一次调用都会立即执行,行为和 Numpy 就完全一致N = 10 ** 7data = mt.random.uniform(-1, 1, size=(N, 2))
inside = (mt.linalg.norm(data, axis=1) < 1).sum()
pi = 4 * inside / N  # 不需要调用 .execute() 了
print('pi: %.5f' % pi.fetch())  # 目前需要 fetch() 来转成 float 类型,后续我们会加入自动转换

Mars DataFrame:pandas 的并行和分布式加速器

看过怎么样轻松把 Numpy 代码迁移到 Mars tensor ,想必读者也知道怎么迁移 pandas 代码了,同样也只有两个区别。我们还是以 movielens 的代码为例。

import mars.dataframe as mdratings = md.read_csv('ml-20m/ratings.csv')
ratings.groupby('userId').agg({'rating': ['sum', 'mean', 'max', 'min']}).execute()

Mars Learn:scikit-learn 的并行和分布式加速器

Mars Learn 也同理,这里就不做过多阐述了。但目前 Mars learn 支持的 scikit-learn 算法还不多,我们也在努力移植的过程中,这需要大量的人力和时间,欢迎感兴趣的同学一起参与。

import mars.dataframe as md
from mars.learn.neighbors import NearestNeighborsdf = md.read_csv('data.csv')  # 输入是 CSV 文件,包含 20万个向量,每个向量10个元素
nn = NearestNeighbors(n_neighbors=10)
nn.fit(df)  # 这里 fit 的时候也会整体触发执行,因此机器学习的高层接口都是立即执行的
neighbors = nn.kneighbors(df).fetch()  # kneighbors 也已经触发执行,只需要 fetch 数据

这里要注意的是,对于机器学习的 fitpredict 等高层接口,Mars Learn 也会立即触发执行,以保证语义的正确性。

RAPIDS:GPU 上的数据科学

相信细心的观众已经发现,GPU 好像没有被提到。不要着急,这就要说到 RAPIDS。

在之前,虽然 CUDA 已经将 GPU 编程的门槛降到相当低的一个程度了,但对于数据科学家们来说,在 GPU 上处理 Numpy、pandas 等能处理的数据无异于天方夜谭。幸运的是,NVIDIA 开源了 RAPIDS 数据科学平台,它和 Mars 的部分思想高度一致,即使用简单的 import 替换,就可以将 Numpy、pandas 和 scikit-learn 的代码移植到 GPU 上。

image

其中,RAPIDS cuDF 用来加速 pandas,而 RAPIDS cuML 用来加速 scikit-learn。

对于 Numpy 来说,CuPy 已经很好地支持用 GPU 来加速了,这样 RAPIDS 也得以把重心放在数据科学的其他部分。

CuPy:用 GPU 加速 Numpy

还是蒙特卡洛求解 Pi。

import cupy as cpN = 10 ** 7data = cp.random.uniform(-1, 1, size=(N, 2))
inside = (cp.sqrt((data ** 2).sum(axis=1)) < 1).sum()
pi = 4 * inside / N
print('pi: %.5f' % pi)

在我的测试中,它将 CPU 的 757ms,降到只有 36ms,提升超过 20 倍,可以说效果非常显著。这正是得益于 GPU 非常适合计算密集型的任务。

RAPIDS cuDF:用 GPU 加速 pandas

将 import pandas as pd 替换成 import cudf,GPU 内部如何并行,CUDA 编程这些概念,用户都不再需要关心。

import cudfratings = cudf.read_csv('ml-20m/ratings.csv')
ratings.groupby('userId').agg({'rating': ['sum', 'mean', 'max', 'min']})

运行时间从 CPU 上的 18s 提升到 GPU 上的 1.66s,提升超过 10 倍。

RAPIDS cuML:用 GPU 加速 scikit-learn

同样是 k-最邻近问题。

import cudf
from cuml.neighbors import NearestNeighborsdf = cudf.read_csv('data.csv')
nn = NearestNeighbors(n_neighbors=10)
nn.fit(df)
neighbors = nn.kneighbors(df)

运行时间从 CPU 上 1min52s,提升到 GPU 上 17.8s。

Mars 和 RAPIDS 结合能带来什么?

RAPIDS 将 Python 数据科学带到了 GPU,极大地提升了数据科学的运行效率。它们和 Numpy 等一样,是命令式的。通过和 Mars 结合,中间过程将会使用更少的内存,这使得数据处理量更大;Mars 也可以将计算分散到多机多卡,以提升数据规模和计算效率。

在 Mars 里使用 GPU 也很简单,只需要在对应函数上指定 gpu=True。例如创建 tensor、读取 CSV 文件等都适用。

import mars.tensor as mt
import mars.dataframe as mda = mt.random.uniform(-1, 1, size=(1000, 1000), gpu=True)
df = md.read_csv('ml-20m/ratings.csv', gpu=True)

下图是用 Mars 分别在 Scale up 和 Scale out 两个维度上加速蒙特卡洛计算 Pi 这个任务。一般来说,我们要加速一个数据科学任务,可以有这两种方式,Scale up 是指可以使用更好的硬件,比如用更好的 CPU、更大的内存、使用 GPU 替代 CPU等;Scale out 就是指用更多的机器,用分布式的方式提升效率。

image

可以看到在一台 24 核的机器上,Mars 计算需要 25.8s,而通过分布式的方式,使用 4 台 24 核的机器的机器几乎以线性的时间提升。而通过使用一个 NVIDIA TESLA V100 显卡,我们就能将单机的运行时间提升到 3.98s,这已经超越了4台 CPU 机器的性能。通过再将单卡拓展到多卡,时间进一步降低,但这里也可以看到,时间上很难再线性扩展了,这是因为 GPU 的运行速度提升巨大,这个时候网络、数据拷贝等的开销就变得明显。

性能测试

我们使用了 https://github.com/h2oai/db-benchmark 的数据集,测试了三个数据规模的 groupby 和 一个数据规模的 join。而我们主要对比了 pandas 和 DASK。DASK 和 Mars 的初衷很类似,也是试图并行和分布式化 Python 数据科学,但它们的设计、实现、分布式都存在较多差异,这个后续我们再撰文进行详细对比。

测试机器配置是 500G 内存、96 核、NVIDIA V100 显卡。Mars 和 DASK 在 GPU 上都使用 RAPIDS 执行计算。

Groupby

数据有三个规模,分别是 500M、5G 和 20G。

查询也有三组。

查询一

df = read_csv('data.csv')
df.groupby('id1').agg({'v1': 'sum'})

查询二

df = read_csv('data.csv')
df.groupby(['id1', 'id2']).agg({'v1': 'sum'})

查询三

df = read_csv('data.csv')
df.gropuby(['id6']).agg({'v1': 'sum', 'v2': 'sum', 'v3': 'sum'})

数据大小 500M,性能结果

image

数据大小 5G,性能结果

image

数据大小 20G,性能结果

image

数据大小到 20G 时,pandas 在查询2会内存溢出,得不出结果。

可以看到,随着数据增加,Mars 的性能优势会愈发明显。

得益于 GPU 的计算能力,GPU 运算性能相比于 CPU 都有数倍的提升。如果单纯使用 RAPIDS cuDF,由于显存大小的限制,数据来到 5G 都难以完成,而由于 Mars 的声明式的特点,中间过程对显存的使用大幅得到优化,所以整组测试来到 20G 都能轻松完成。这正是 Mars + RAPIDS 所能发挥的威力。

Join

测试查询:

x = read_csv('x.csv')
y = read_csv('y.csv')
x.merge(y, on='id1')

测试数据 x 为500M,y 包含10行数据。

image

总结

RAPIDS 将 Python 数据科学带到了 GPU,极大提升了数据分析和处理的效率。Mars 的注意力更多放在并行和分布式。相信这两者的结合,在未来会有更多的想象空间。

Mars 诞生于 MaxCompute 团队,MaxCompute 原名 ODPS,是一种快速、完全托管的EB级数据仓库解决方案。Mars 即将通过 MaxCompute 提供服务,购买了 MaxCompute 服务的用户届时可以开箱即用体验 Mars 服务。敬请期待。

原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/516371.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue2.x vant2.x H5 移动端脚手架

文章目录一、前置准备1. 技术选型2. 创建vue项目二、Rem 布局适配2.1. px转rem2.2. 设置 rem 基准值2.3. 配置vue.config.js2.4. 重置样式表2.5. 配置样式表2.6. 安装less2.7. 注册less2.8. 代码中使用三、vant安装/配置/测试3.1. 安装vant-ui3.2. 引入与注册3.3. vant测试四、…

相见恨晚!遗憾仅有不到1% 的人知道

广泛在各领域被应用的数据分析&#xff0c;现在已经是任何岗位任何职业都需要用到的技能。即便不从事职业的数据分析&#xff0c;掌握一定的数据处理能力也将成为你职场中绝对的加分项。为了跟上人才市场的能力需求&#xff0c;许多做技术开发的同学也加入了数据分析的学习热潮…

【机器人】标记不友好评论,AI工作效果是人类的4.4倍

云栖号资讯&#xff1a;【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯&#xff0c;还在等什么&#xff0c;快来&#xff01; 不友好的评论对于系统而言是一个大问题&#xff0c;因为他们的语气会影响被评论者和未来读者对 Stack Overflow 的贡献意愿。…

VBA 常用代码及自定义函数备忘

文章目录 1. 函数1.1 Windows API1.1.1 改变当前鼠标指针形状1.1.2 Sleep 程序休眠1.2 自定义函数1.2.1 去除空格1.2.2 测试图片格式1.2.3 获取打印机信息1.2.4 GB/T 8170 修约1.2.5 邮箱格式检查1.2.6 汉字转拼音1.2.7 列标签字母与列序号数值转换1.2.8 大小写金额转换1.2.9 分…

2020年云计算的十大新兴趋

云栖号资讯&#xff1a;【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯&#xff0c;还在等什么&#xff0c;快来&#xff01; 人们将在2020年可能会看到一些顶级云计算趋势主题&#xff0c;其中包括人工智能、自动化和多云的更大发展。 随着越来越多的…

各企业正在纷纷向“云”,背后有着哪些原因?

撰者 | Emil Sayegh译者 | Katie&#xff0c;责编 | Jerry来源 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;在全球大流行的初期&#xff0c;各地企业的目标很简单&#xff1a;继续运营。社交隔离要求使得零售&#xff0c;银行&#xff0c;医疗&#xff0c;教…

如何在Java代码中去掉烦人的“!=null”

云栖号资讯&#xff1a;【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯&#xff0c;还在等什么&#xff0c;快来&#xff01; 问题 为了避免空指针调用&#xff0c;我们经常会看到这样的语句 if (someobject ! null) {someobject.doCalc(); } 最终&a…

vue TypeError: Cannot read property ‘upgrade‘ of undefined

这个错误的原因是&#xff1a; vue.config.js 中配置的 proxy 中的 target 上设置的 process.env.xxxxx 不存在。

吐血整理:手拿几个大厂offer的秘密武器!

怎样才能拿到大厂的offer&#xff1f;没有掌握绝对的技术&#xff0c;那么就要不断的学习。如何拿下阿里等大厂的offer呢&#xff0c;今天分享一个秘密武器&#xff0c;资深架构师整理的Java核心知识点&#xff0c;面试时面试官必问的知识点&#xff0c;篇章包括了很多知识点&a…

拿下 Gartner 容器产品第一,阿里云打赢云原生关键一战!

云栖号资讯&#xff1a;【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯&#xff0c;还在等什么&#xff0c;快来&#xff01; 近日&#xff0c;Gartner 发布 2020 年公共云容器报告&#xff0c;据报告显示&#xff0c;阿里云和 AWS 拥有最丰富的产品布局…

银河证券上云 打开互联网金融思维的魔盒

云栖号案例库&#xff1a;【点击查看更多上云案例】 不知道怎么上云&#xff1f;看云栖号案例库&#xff0c;了解不同行业不同发展阶段的上云方案&#xff0c;助力你上云决策&#xff01; 近些年&#xff0c;很多证券公司纷纷设立“互联网金融”部门&#xff0c;推出创新业务&a…

如何轻松地将可访问LAN的Pod部署到Kubernetes集群上

撰者 | Jack Wallen 译者 | Katie&#xff0c;责编 | Jerry来源 | CSDN云计算封图 | CSDN 下载自视觉中国想要在Kubernetes集群上部署可访问LAN的Pod来达到目的&#xff1f;接下来就展示一下它实际上是多么容易。Kubernetes更具挑战性的方面之一是部署到集群&#xff0c;同时使…

车市下滑 领克汽车为什么逆势上扬?

云栖号案例库&#xff1a;【点击查看更多上云案例】 不知道怎么上云&#xff1f;看云栖号案例库&#xff0c;了解不同行业不同发展阶段的上云方案&#xff0c;助力你上云决策&#xff01; 2018年末开始&#xff0c;寒潮席卷中国汽车市场。热了20多年的中国车市&#xff0c;迎来…

使用Vant完成DatetimePicker 日期的选择器

效果演示&#xff1a; 代码 <template><div> <!-- 输入框形式--><van-fieldreadonlyclickablename"calendar":value"timeValue"label"日期选择&#xff1a;"placeholder"发生事故的时间点"click"showP…

彩生活云上转型 打造全球最大社区服务运营商

云栖号案例库&#xff1a;【点击查看更多上云案例】 不知道怎么上云&#xff1f;看云栖号案例库&#xff0c;了解不同行业不同发展阶段的上云方案&#xff0c;助力你上云决策&#xff01; 在房地产行业增速放缓的大环境下&#xff0c;转型焦虑几乎已经弥漫整个地产行业&#xf…

谷歌这波操作,预警了什么信号??

我们都知道谷歌爸爸收购了Cask Data一家公司。长期以来&#xff0c;谷歌致力于推动围绕 GoogleCloud 的企业业务&#xff0c;但在这方面一直被亚马逊和微软吊打&#xff0c;这次的收购正是为了弥补自身的短板。被收购的 Cask Data 是一家专门提供基于Hadoop的大型数据分析服务解…

【开发者成长】“机器学习还是很难用!”

云栖号资讯&#xff1a;【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯&#xff0c;还在等什么&#xff0c;快来&#xff01; 机器学习仍然很难用&#xff0c;但情况开始有所改善了。 以下为译文&#xff1a; 我是一名Cortex贡献者&#xff0c;Cortex是…

这个年均开销3500万美元的 FBI 机密部门,将结合面部识别与大数据技术来调查案件...

撰者 | Thomas Brewster译者 | Katie&#xff0c;责编 | Jerry来源 | CSDN云计算FBI面部识别大数据&#xff0c;瞄准恐怖犯罪事件在发生大规模枪击或恐怖袭击后&#xff0c;调查人员可能会留有数小时的闭路电视录像&#xff0c;证人的视频或社交媒体的剪辑。以2013年的波士顿马…

节省50%部署时间的5大KS8服务

云栖号资讯&#xff1a;【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯&#xff0c;还在等什么&#xff0c;快来&#xff01; Kubernetes已然成为IT世界的重要组成部分&#xff0c;并且仍在不断地发展壮大&#xff0c;现阶段&#xff0c;Kubernetes已经…