You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark Standalone模式增加Worker后执行时间近乎恒定的原因探究

Spark Worker数超过核心数后性能未下降的原因

问题背景

我了解到使用Spark时建议按每个核心配置一个Worker,但实际测试时,当设置的Worker数量远超过电脑核心数(我的Mac是2核i5),性能并未出现下降。想请教该现象的原因。

测试代码

from time import time
from pyspark import SparkContext

for j in range(1, 10):
    sc = SparkContext(master="local[%d]" % (j))
    t0 = time()
    for i in range(10):
        sc.parallelize([1, 2] * 1000000).reduce(lambda x, y: x + y)
    print("%2d executors, time=%4.3f" % (j, time() - t0))
    sc.stop()

# 运行结果:
# 1 executors time=6.112
# 2 executors time=5.202
# 3 executors time=4.695
# 4 executors time=5.090
# 5 executors time=5.262
# 6 executors time=5.156
# 7 executors time=5.274
# 8 executors time=5.376
# 9 executors time=5.124

硬件配置

  • MacBook Pro
  • Intel Core i5,2.3GHz
  • 总物理核心数:2个
  • L2缓存:256 KB
  • L3缓存:4 MB
  • 内存:16 GB

这是个很有意思的观察!结合你的硬件、测试代码和运行结果,咱们可以从三个核心角度解释这个现象:

1. 超线程带来的逻辑核心扩展

你的Intel Core i5支持超线程技术——每个物理核心可以模拟出2个逻辑核心,所以系统实际能同时调度的并行线程数是4个(2物理核心 × 2逻辑核心)。这就解释了为什么设置1-4个executors时,任务时间逐步下降:此时线程数逐步填满所有逻辑核心,计算效率不断提升。当线程数超过4个后,操作系统会通过时间片轮转调度这些线程共享逻辑核心,但因为线程切换的开销(同一进程内的线程切换成本远低于进程切换)极小,所以不会导致性能明显下降。

2. Local模式下Executor是线程而非独立进程

在Spark的local[N]模式中,N代表的是执行线程数,而非独立的Worker进程。这些线程共享同一个JVM(PySpark中则是共享Python进程的线程池),线程间的上下文切换不需要切换地址空间,开销非常低。即使线程数超过逻辑核心数,操作系统调度器也能高效地在这些线程间切换,不会带来显著的性能损耗。

3. 轻量级测试任务的特性

你的测试任务是简单的reduce加法操作,属于轻量级计算任务,且数据完全在本地内存中(通过parallelize生成RDD,无网络IO开销)。这类任务的CPU计算占比相对较低,线程在执行过程中可能存在微小的空闲间隙(比如数据序列化/反序列化的短暂等待),额外的线程可以利用这些间隙执行计算,因此不会明显拖慢整体任务时间。

从你的运行结果也能验证这一点:4个executors之后,任务时间稳定在5.1-5.3秒左右,没有出现预期中的性能下降,只是不再有性能提升——这说明超过逻辑核心数后,线程调度的开销被任务本身的特性抵消了。

内容的提问来源于stack exchange,提问作者Arnold Taremwa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:25:59