在pyspark中计算Spark数据帧组的并行化

时间:2017-10-11 22:19:40

标签: python apache-spark pyspark

我在名为part-0001part-0002的Linux计算机上的单个目录中有大约200个文件,依此类推。每个行都有大约一百万行具有相同的列(称为'a','b',依此类推)。让对'a','b'成为每行的关键(有许多重复)。

与此同时,我已经建立了一个Spark 2.2.0集群,其中包含一个主服务器和两个从服务器,共有42个可用核心。地址为spark://XXX.YYY.com:7077

然后我使用PySpark连接到群集并计算每个唯一对的200个文件的计数,如下所示。

from pyspark import SparkContext
from pyspark.sql import SQLContext
import pandas as pd

sc = SparkContext("spark://XXX.YYY.com:7077")
sqlContext = SQLContext(sc)

data_path = "/location/to/my/data/part-*"
sparkdf = sqlContext.read.csv(path=data_path, header=True)
dfgrouped = sparkdf.groupBy(['a','b'])
counts_by_group = dfgrouped.count()

这是因为我可以看到Spark通过一系列消息进展,它确实返回看似合理的结果。

问题:执行此计算时,top没有显示任何从属内核正在执行任何操作的证据。似乎没有任何并行化。每个从属服务器都有一个相关的Java进程,该进程在作业之前就已存在(加上来自其他用户和后台系统进程的进程)。所以看来主人正在做所有的工作。鉴于有200个奇怪的文件,我原本希望在每个从机上运行21个进程,直到事情结束(这个是我在显式调用parallelize时看到的内容如下{{ 1}}在一个单独的实现中。)

问题:我如何确保Spark实际并行计数?我希望每个核心都能获取一个或多个文件,对它在文件中看到的对执行计数,然后将单个结果缩减为单个count = sc.parallelize(c=range(1, niters + 1), numSlices=ncores).map(f).reduce(add)。我不应该在顶部看到这个吗?我是否需要显式调用并行化?

(FWIW,我见过使用分区的例子,但我的理解是这用于在单个文件的块上分发处理。我的情况是我有很多文件。)

提前致谢。

1 个答案:

答案 0 :(得分:2)

TL; DR 您的部署可能没有任何问题。

  

我原本预计会看到21个进程正在运行

除非您专门配置Spark以使用每个执行程序JVM的单个核心,否则没有理由这样做。与您在问题中提到的RDD示例不同,DataFrame API根本不使用Python工作者,但Python UserDefinedFunctions除外。

同时,JVM执行程序使用线程而不是完整的系统进程(PySpark使用后者来避免GIL)。此外,独立模式下的默认spark.executor.cores等于the available cores on the worker的数量。因此,如果没有其他配置,您应该看到两个执行程序JVM,每个JVM使用21个数据处理线程。

总的来说,你应该检查Spark UI,如果你看到分配给执行者的任务,一切都应该没问题。