独立集群 + Docker 上的 PySpark 性能不佳
Posted
技术标签:
【中文标题】独立集群 + Docker 上的 PySpark 性能不佳【英文标题】:Poor PySpark performance on Stand-alone cluster + Docker 【发布时间】:2016-08-23 09:55:45 【问题描述】:我在 AWS c4.8xlarge 机器(一台或多台)上的 Docker 容器内运行 Spark 从站,与仅在笔记本电脑上使用 multiprocessing(使用四核 Intel i7)相比,我很难获得预期的性能-6820HQ)。 (请参阅下面的编辑,相同的硬件也会产生巨大的开销)
我正在寻找可以在单线程、多进程或分布式 Spark 场景中工作的“多处理器”水平扩展分析模型训练的解决方案:
class Multiprocessor:
# ...
def map(self, func, args):
if has_pyspark:
n_partitions = min(len(args), 1000)
return _spark_context.parallelize(args, n_partitions).map(func).collect()
elif self.max_n_parallel > 1:
with multiprocessing.Pool(self.max_n_parallel) as pool:
return list(pool.map(func, args))
else:
return list(map(func, args))
如您所见,Spark 的作用是分发计算并简单地检索结果,parallelize().map()
是唯一使用的 API。 args
只是一个整数 id 元组的列表,没有太重。
我正在使用 Docker 1.12.1 (--net host
)、Spark 2.0.0(独立集群)、Hadoop 2.7、Python 3.5 和 openjdk-7。相同训练数据集的结果,每次运行都受 CPU 限制:
local[4]
)
7.7 分钟,三个 c4.8xlarge 从属设备(每个使用 10 个内核)
25 分钟,单个 c4.8xlarge 从属设备(10 核)(!)
27 分钟,本地 VM Spark 从站(4 核)(!)
所有 36 个虚拟 CPU 似乎都在使用,平均负载为 250 - 350。要映射大约 360 个args
值,它们的处理时间为 15 - 45 秒(第 25 和第 75 个百分位数)。 CG时间是微不足道的。甚至尝试返回“空”结果以避免网络开销,但这并不影响总时间。通过 *** Ping 到 AWS 需要 50 - 60 毫秒。
关于我应该研究哪些其他指标的任何提示,我觉得我在某处浪费了大量的 CPU 周期。我真的很想围绕 Spark 构建架构,但基于这些 PoC,至少 AWS 上的机器太贵了。必须使用我可以访问的其他本地硬件进行测试。
编辑 1:在笔记本电脑上的 Linux VM 上进行测试,使用独立集群需要 27 分钟,比使用 local[4]
多 20 分钟。
编辑 2:每个从属“核心”似乎有 7 个 pyspark 守护进程,所有这些都占用大量 CPU 资源。这是预期的行为吗? (图片来自笔记本电脑的虚拟机)
编辑 3:实际上,即使只启动一个单核从属设备也会发生这种情况,我得到 100% 的 CPU 利用率。根据this answer 红色表示内核级线程,Docker 可以在这里发挥作用吗?无论如何,我不记得在使用 Python 2.7 进行原型设计时看到过这个问题,我得到的性能开销非常小。现在更新到 Java OpenJDK 8,它没有任何区别。 Spark 1.5.0 和 Hadoop 2.6 也得到了相同的结果。
编辑 4:我可以追踪到默认情况下 scipy.linalg.cho_factor
使用所有可用内核,这就是为什么我看到即使 Spark slave 使用一个内核时 CPU 使用率也很高的原因。必须进一步调查...
最终编辑:这个问题似乎与 AWS 或 Spark 无关,我在 Docker 容器中的独立 Python 上的性能很差。见我的answer below。
【问题讨论】:
【参考方案1】:有同样的问题 - 对我来说,根本原因是内存分配。 确保为 spark 实例分配足够的内存。 在 start-slave.sh - 运行 --help 以获取内存选项(默认为每个节点 1GB,无论机器中的实际内存如何)。
您可以在 UI(master 上的端口 8080)中查看每个节点分配的内存。
您还需要在提交应用程序时设置每个执行程序的内存,即 spark-submit(再次默认为 1GB),就像以前一样 - 使用 --help 运行以获取内存选项。
希望这会有所帮助。
【讨论】:
【参考方案2】:很抱歉造成混乱(我是 OP),我花了一段时间才深入了解真正发生的事情。我做了很多基准测试,最后我意识到在 Docker 映像上我使用的是 OpenBLAS,它默认使用多线程 linalg 函数。我的代码在80 x 80
到140 x 140
大小的矩阵上运行了数百次cho_solve
。启动所有这些线程只会产生大量开销,而我一开始并不需要这些开销,因为我正在通过多处理或 Spark 进行并行计算。
# N_CORES=4 python linalg_test.py
72.983 seconds
# OPENBLAS_NUM_THREADS=1 N_CORES=4 python linalg_test.py
9.075 seconds
【讨论】:
以上是关于独立集群 + Docker 上的 PySpark 性能不佳的主要内容,如果未能解决你的问题,请参考以下文章
Hadoop 独立集群 Pyspark 加载 CSV 文件不存在(hdfs://home/usr/filepath.csv)
从 Docker 容器将 PySpark 连接到 Kafka
K3s 集群内 containerd 跟 docker 的区别