我在AWS c4.8xlarge计算机(一个或多个)上的Docker容器中运行Spark slave,与在笔记本电脑上使用multiprocessing相比,难以获得预期的性能(四核英特尔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]
)所有36个虚拟CPU似乎都在使用中,平均负载为250 - 350.大约有360 args
个值被映射,它们的处理时间为15 - 45秒(第25和第75百分位数)。 CG时代微不足道。甚至尝试返回“空”结果以避免网络开销,但它不会影响总时间。通过VPN Ping到AWS的时间为50 - 60 ms。
我应该研究哪些其他指标的提示,觉得我在某处浪费了很多CPU周期。我真的很想围绕Spark构建架构,但基于这些PoC,至少AWS上的机器太贵了。必须使用我可以访问的其他本地硬件进行测试。
编辑1 :在笔记本电脑上的Linux VM上测试,使用独立群集需要27分钟,比使用local[4]
多20分钟。
编辑2 :每个从属“核心”似乎有7个pyspark守护进程,所有这些都占用了大量的CPU资源。这是预期的行为吗? (图片来自笔记本电脑的VM)
编辑3 :实际上即使只启动一个核心,也会发生这种情况,我获得了100%的CPU利用率。根据{{3}}红色表示内核级线程,Docker可以在这里发挥作用吗?无论如何,我不记得在使用Python 2.7进行原型设计时看到这个问题,我的性能开销非常小。现在更新到Java OpenJDK 8,它没有任何区别。 Spark 1.5.0和Hadoop 2.6也得到了相同的结果。
编辑4 :我可以追踪到默认情况下scipy.linalg.cho_factor
使用所有可用内核,这就是为什么我看到高CPU使用率,即使有一个核心用于Spark奴隶。必须进一步调查......
答案 0 :(得分:1)
有同样的问题 - 对我来说,根本原因是内存分配。 确保为spark实例分配足够的内存。 在start-slave.sh中 - 运行--help以获取内存选项(无论机器中的实际内存如何,每个节点的默认值为1GB)。
您可以在UI(主设备上的端口8080)中查看每个节点分配的内存。
您还需要在提交应用程序时设置每个执行程序的内存,即spark-submit(再次默认为1GB),就像之前一样 - 运行--help来获取内存选项。
希望这有帮助。
答案 1 :(得分:0)
很抱歉这个混乱(我是OP),我花了一段时间来深入了解真正发生的事情。我做了很多基准测试,最后我意识到在Docker镜像上我使用的是OpenBLAS,默认情况下是多线程linalg函数。我的代码在大小不等的TestTrait
到cho_solve
的矩阵上运行80 x 80
数百次。启动所有这些线程只需要很多开销,因为我通过多处理或Spark进行并行计算,所以我首先不需要这些线程。
140 x 140