节点上的Spark分区foreachpartition

时间:2019-06-26 10:20:29

标签: performance apache-spark parallel-processing google-cloud-dataproc

我有一个火花集群(DataProc),其中有一个主服务器和4个工作器(两个可转换),在我的代码中,我有这样的东西:

    JavaRDD<Signal> rdd_data = javaSparkContext.parallelize(myArray);
rdd_data.foreachPartition(partitionOfRecords -> {
        while (partitionOfRecords.hasNext()) {
            MyData d = partitionOfRecords.next();
            LOG.info("my data: " + d.getId().toString());
        }
    })

myArray由1200个MyData对象组成。 我不明白为什么spark只使用2个核心,将数组划分为2个分区,而不使用16个核心。 我需要设置分区数吗?

在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

通常,将分区数指定为parallelize的第二个参数总是一个好主意,因为数据集的最佳切片实际上应该与所使用的群集的特定形状无关,并且Spark最多只能将执行程序的当前大小用作“提示”。

您在这里看到的是,Spark将默认要求taskScheduler要求current number of executor cores用作defaultParallelism,并结合启用了Dataproc Spark dynamic allocation的事实。动态分配很重要,因为否则,即使提交到集群的单个作业即使处于空闲状态也可能仅指定最大执行者,然后这将阻止其他作业使用这些空闲资源。

因此在Dataproc上,如果您使用默认的n1-standard-4,则Dataproc会在每台计算机上配置2个执行程序,并为每个执行程序提供2个内核。 spark.dynamicAllocation.minExecutors的值应为1,因此您的默认作业在启动时不做任何工作,将坐在1个具有2个核心的执行程序上。然后taskScheduler将报告当前总共保留了2个内核,因此defaultParallelism将为2。

如果您有一个大型集群,并且已经运行了一段时间(例如,您的映射阶段运行了60秒以上),则您希望动态分配占用了所有可用资源,因此下一个这样,使用defaultParallelism的工作的步骤大概是16,这是群集上的总核心数(如果一个应用程序管理员消耗了2个核心,则可能是14)。

实际上,您可能想将并行化的分区数量多于总可用核心数。然后,如果每个元素处理的时间有任何偏差,则可以很好地平衡快速任务的完成位置,然后那些执行者可以在慢速分区仍在运行时开始采用新分区,而不必总是等待一个分区最慢的分区完成。通常会选择任意数量的分区,范围从可用核心数量的2倍到100x甚至更多。

这是另一个与StackOverflow相关的问题:spark.default.parallelism for Parallelize RDD defaults to 2 for spark submit