锐眼洞察 | 利用Apache Arrow来加速PySpark(翻译)

作者:Bryan Cutler

原文:Speeding up PySpark with Apache Arrow

译者:TalkingData首席架构师 黄洋成(YC)

本译文禁止商用,转载请注明来源与译者!

 

Apache Spark 2.3版本开始,Apache Arrow成为一个被支持的依赖组件,可以为列式数据传输提供更好的性能。如果你是一个Spark用户,但是偏好利用Python和Pandas,那你应该有理由兴奋!目前初步的工作(下面会介绍到)还局限于加速 toPandas() 里从Spark的DataFrame中传递数据;但有一大波其他的改进正在路上

优化从Spark到Pandas的数据转换

以前在PySpark里利用 DataFrame.toPandas() 将数据从Spark DataFrame转换到Pandas是非常低效的。基本上其工作机制是:首先从Spark driver把所有的行汇集起来,然后每一行都会被序列化为Python的pickle格式,发给Python的worker进程;这个子进程会反序列化每一行,拼成一个大list;最后利用 pandas.DataFrame.from_records() 从这个list来创建一个Pandas DataFrame。

这听起来像是一个标准过程,但有两个明显问题:1)即使使用CPickle,Python的序列化也是一个很慢的过程;2)利用 from_records 来创建一个 pandas.DataFrame 需要遍历Python list,将每个value转换成Pandas格式,这里有对这个过程的详细分析。

Arrow可以优化这几个步骤:1)一旦数据变成了Arrow的内存格式,就不再有序列化的需要,因为Arrow数据可以直接发送到Python进程;2)当在Python里接收到Arrow数据后,pyarrow可以利用zero-copy技术,一次性的从整片数据来创建 pandas.DataFrame,而不需要轮询去处理每一行记录。另外转换成Arrow数据的过程可以在JVM里并行完成,这样可以显著降低driver的压力。

在SPARK-13534的归并中,要在 toPandas() 里打开使用Arrow的功能,需要将SQLConf里的设置“spark.sql.execution.arrow.enabled” 设为 “true”。下面让我们来看一个简单的例子:

图片 1

 

这是在笔记本电脑上面跑的,所以显示的执行时间未必精确;但是可以看出使用Arrow后性能有了巨大的提升(从20.7s降低到737ms)。

使用的注意事项

下边是使用这个feature时候需要注意的地方:目前pyarrow还不会随着安装pyspark自动安装,而是需要手动安装(参考安装指南)。计划会把pyarrow作为pyspark的一个依赖组件,那样 > pip install pyspark 就会自动把pyarrow也装上了。

目前SQLConf里的enable Arrow的设置缺省是关闭的,需要在程序里手动打开(如上边例子所示),或者也可以收到修改 SPARK_HOME/conf/spark-defaults.conf,加上一行“spark.sql.execution.arrow.enabled=true”。

另外不是所有Spark的数据类型都是支持的,目前只支持基础数据类型。扩展的数据类型支持正在开发中,预期能包含在Spark 2.3版本的发布里。

将来的改进计划

记住这只是利用Arrow来让提升Spark Python的用户体验的一小步。一些激动人心的提议包括UDF的向量化执行(SPARK-21190SPARK-21404),可以apply一个function到Pandas DataFrame(SPARK-20396)。另外就像Arrow能帮到数据从Spark转换到Pandas一样,他也可以帮助从Pandas DataFrame转换为Spark DataFrame(SPARK-20791)。

发表评论

电子邮件地址不会被公开。 必填项已用*标注