独立群集+ Docker

时间:2016-08-23 09:55:45

标签: amazon-web-services apache-spark pyspark

我在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限制:

  • 使用本地多处理(4个进程)5.4分钟
  • 5.9分钟,带有四个c4.8xlarge奴隶(每个使用10个核心/每个)
  • 6.9分钟与当地Spark(主人local[4]
  • 使用三个c4.8xlarge奴隶(每个使用10个核心/每个)的7.7分钟
  • 使用单个c4.8xlarge slave(10个核心)(!)
  • 25分钟
  • 使用本地VM Spark slave(4核)(!)
  • 27分钟

所有36个虚拟CPU似乎都在使用中,平均负载为250 - 350.大约有360 args个值被映射,它们的处理时间为15 - 45秒(第25和第75百分位数)。 CG时代微不足道。甚至尝试返回“空”结果以避免网络开销,但它不会影响总时间。通过VPN Ping到AWS的时间为50 - 60 ms。

htop

我应该研究哪些其他指标的提示,觉得我在某处浪费了很多CPU周期。我真的很想围绕Spark构建架构,但基于这些PoC,至少AWS上的机器太贵了。必须使用我可以访问的其他本地硬件进行测试。

编辑1 :在笔记本电脑上的Linux VM上测试,使用独立群集需要27分钟,比使用local[4]多20分钟。

编辑2 :每个从属“核心”似乎有7个pyspark守护进程,所有这些都占用了大量的CPU资源。这是预期的行为吗? (图片来自笔记本电脑的VM)

pyspark daemons

编辑3 :实际上即使只启动一个核心,也会发生这种情况,我获得了100%的CPU利用率。根据{{​​3}}红色表示内核级线程,Docker可以在这里发挥作用吗?无论如何,我不记得在使用Python 2.7进行原型设计时看到这个问题,我的性能开销非常小。现在更新到Java OpenJDK 8,它没有任何区别。 Spark 1.5.0和Hadoop 2.6也得到了相同的结果。

this answer

编辑4 :我可以追踪到默认情况下scipy.linalg.cho_factor使用所有可用内核,这就是为什么我看到高CPU使用率,即使有一个核心用于Spark奴隶。必须进一步调查......

最终编辑:这个问题似乎与AWS或Spark无关,我在Docker容器中的独立Python上表现不佳。查看我的pyspark daemons 2

2 个答案:

答案 0 :(得分:1)

有同样的问题 - 对我来说,根本原因是内存分配。 确保为spark实例分配足够的内存。 在start-slave.sh中 - 运行--help以获取内存选项(无论机器中的实际内存如何,每个节点的默认值为1GB)。

您可以在UI(主设备上的端口8080)中查看每个节点分配的内存。

您还需要在提交应用程序时设置每个执行程序的内存,即spark-submit(再次默认为1GB),就像之前一样 - 运行--help来获取内存选项。

希望这有帮助。

答案 1 :(得分:0)

很抱歉这个混乱(我是OP),我花了一段时间来深入了解真正发生的事情。我做了很多基准测试,最后我意识到在Docker镜像上我使用的是OpenBLAS,默认情况下是多线程linalg函数。我的代码在大小不等的TestTraitcho_solve的矩阵上运行80 x 80数百次。启动所有这些线程只需要很多开销,因为我通过多处理或Spark进行并行计算,所以我首先不需要这些线程。

140 x 140