假设有10k个简单的直接任务要做,哪一个更好?
//method 1
spark.parallize(range(1,10k)).map(taskDone)
//method 2
range(1, 10k).stream().parallel().map(spark.rdd(x).collect() /*do one using spark*/)
它们是等价的吗?或者哪一个是首选?
假设有10k个简单的直接任务要做,哪一个更好?
//method 1
spark.parallize(range(1,10k)).map(taskDone)
//method 2
range(1, 10k).stream().parallel().map(spark.rdd(x).collect() /*do one using spark*/)
它们是等价的吗?或者哪一个是首选?
1条答案
按热度按时间ckx4rj1h1#
这是根本不同的。
一方面
这将在本地(在驱动程序节点上)创建一个包含10k元素的范围对象。这个范围被传送到集群的executor节点(每个接收n个元素),每个worker将任务应用到这n个元素,而驱动程序(可能是因为这里需要最后一步来真正开始计算)等待返回结果。
更具体地说:
是在驱动程序上单线程运行的代码。它所做的是创建一个范围,并要求spark将其拆分(将其发送到executor节点)
然后
将代码发送到
taskDone
以使任务在触发计算后在集群允许的范围内并发应用。另一方面。。。
这将在驱动程序上创建一个范围,包含10k元素。然后,将10k元素中的每一个并行地(并行级别是一台机器的并行级别,驱动程序节点,与集群无关)分配给rdd(包含单个元素),并且(大概)为集群创建10k任务,每个任务在单个元素上工作。
这种第二种做事方式几乎肯定会非常低效。spark被设计成分布式地处理(非常)大的集合,使用的编程模型使它看起来像是在本地处理的。这是您的第一个代码示例。
您的第二个代码的工作方式与此相反:它在一台“计算机”(主节点)上创建大量非常小的集合,这违背了目的:将单个元素的集合传送到计算集群是没有用的!
更具体地说:
这是在一台计算机(驱动程序)上串行运行的代码。它创建一个范围,将其(平行地)拆分为单个(size=1)元素,并将这些单个元素中的每个元素转换为该单个元素的rdd(spark分布式集合)。
实现的并行级别是驱动程序节点的并行级别。并行化的是RDD的创建,而不是对元素执行工作
然后:
您要求执行并收回每个rdd。只要sparksession是线程安全的和并发的,那么这些非常小的(1项)rdd就会被处理并发回。
因此,您将并行性限制为驱动程序节点的并行性(通常没有那么大),而不是使用集群的并行性(可能非常大)。
用第一种方法。