我有一个数据集,我想并行运行多个作业。我通过在自己的线程中启动每个操作来实现这一点,以便像文档中所说的那样为每个Spark应用程序获得多个Spark作业。
现在,我正在运行的任务并没有从投入更多的内核中获得无穷无尽的好处——大约50个内核左右,添加更多资源的收益是非常小的。例如,如果我有两个作业和100个核心,我想并行运行两个作业,每个作业最多只占用50个核心,以获得更快的结果。
我可能会做的一件事是将分区数量设置为50,这样作业只能生成50个任务(?)。但是显然,拥有比可用内核更多的分区可以获得更好的总体利用率,从而带来一些性能上的好处。
但除此之外,我没有在文档中发现任何有用的东西来限制每个Apache Spark作业在一个应用程序中的资源。(我希望避免生成多个应用程序来分割执行器)。
有什么好的方法可以做到这一点吗?
也许要求Spark驱动使用公平调度是最适合您的情况的解决方案。
从Spark 0.8开始,也可以在作业之间配置公平共享。在公平共享下,Spark以"循环"的方式在作业之间分配任务,这样所有作业都可以获得大致相等的集群资源份额。这意味着在运行长作业时提交的短作业可以立即开始接收资源,并且仍然可以获得良好的响应时间,而无需等待长作业完成。此模式最适合多用户设置。
还有一个池的概念,但我没有使用它们,也许它在公平调度的基础上给了你更多的灵活性。
似乎是相互冲突的需求,没有灵丹妙药。
- 尽量并行化。
- 限制任何一个作业占用资源,当(且仅当)另一个作业正在运行。
:
- 如果你增加分区的数量,那么你将地址#1而不是#2。
- 如果您指定
spark.cores.max
,那么您将处理#2而不是#1。 - 如果你同时做了(更多分区和限制
spark.cores.max
),那么你将处理#2而不是#1。
如果你只增加分区数量,那么你唯一冒的风险是长时间运行的大作业将延迟一些较小作业的完成/执行,尽管总的来说,只要你不限制并发(spark.cores.max
),在给定的硬件上以任何顺序运行两个作业将花费相同的时间。
一般情况下,我会避免限制并发性(spark.cores.max
)。
IMO的底线
- 不要碰
spark.cores.max
. - 如果你没有使用所有的内核,请增加分区。
- 使用公平调度
- 如果您有严格的延迟/响应时间要求,那么为长时间运行和短时间运行的作业使用单独的自动伸缩集群