我认为我有一个初学者错误,但我真的不知道如何修复它,这让我疯了。 我有一个由2台机器组成的集群:
我有一个类网络,我想通过从具有单个网络的列表开始,然后通过使用flatmap将每个网络转换为N个新网络,在for循环中生成网络。之后,我有一个过滤器和一个计数。步骤进行:
JavaSparkContext sc = new JavaSparkContext(conf);
List<Network> data = Arrays.asList(new Network());
JavaRDD<Network> currentN = sc.parallelize(data);
for(int k=1;k<=10;k++) {
JavaRDD<Network> newN = currentN.flatMap(new MyFlatMap());
currentN = newN;
}
JavaRDD<Network> filteredNetworks = currentN.filter(new MyFilter());
System.out.println(filteredNetworks.count());
算法工作并输出正确的值。
但是,通过比较不同场景中应用程序的持续时间,我倾向于认为应用程序不是并行运行的:
使用两台机器的群集,共有2GB的Ram和8个核心:持续时间1.5分钟
仅使用第二台计算机(VM Ubuntu),1GB RAM,4核心的群集:持续时间1,1分钟
仅使用第一台计算机(主计算机,工作程序和驱动程序)的群集,1GB RAM,4核心:持续时间3,2分钟
我的火花UI的截图:
我不知道为什么在虚拟机中运行Ubuntu的机器比主机(主机,工程师和驱动程序)更快,因为主机有更好的CPU(i7 2.6GHZ与i3相比) ,9GHz的)。
但主要的问题是为什么在一台机器上运行比在两台机器上运行更快?不应该是相反的吗?我的猜测是RDD不是并行计算的。如果是这种情况,请您解释为什么以及如何让它并行处理?
解释作业的作用:
基本上,这是我想在for循环中实现的目标:
我从一个网络的RDD开始(它不是一个文件,它只是一个小类)。
在for循环中,我使用flatMap将1个网络转换为10个新网络。
迭代0:currentN = 1网络 - &gt; flatMap - &gt; currentN = 10网络
迭代1:currentN = 10网络 - &gt; flatMap - &gt; currentN = 100网络
。
迭代9:currentN = 10 ^ 8网络 - &gt; flatMap - &gt; currentN = 10 ^ 9网络
正如我所说,我生成输入。我想并行生成这个,所以这意味着flatMap需要并行完成。要做到这一点,火花应该:
带有N个网络的RDD
将RDD划分为每个核心的8个分区,每个分区具有N / 8个网络
并行地在每台机器上应用flatMap,将每个N / 8网络转换为N / 8 * 10个新网络。
在每台机器上重复这些步骤,并行执行flatMap生成。
for循环结束后,每台机器应该有10 ^ 9/8网络。并行过滤它们,然后在parralel中计算每台机器上每个RDD中的元素数量并输出答案。
这是我想要实现的,但由于某种原因,for循环中的flatMap生成仅在一台机器上完成。
答案 0 :(得分:1)
来自spark UI的最后一个屏幕截图显示,在8个任务中,7个已完成,最长时间为37毫秒,而最长的任务至少运行46秒。
如果你有一个任务运行3分钟,而其他任务运行不到一秒钟,你的分布式计算不平衡,因此你无法利用多台机器完全运行,因为计算时间受最长时间的限制任务。
这种行为通常是由不平衡操作/转换(join
,...)输入不平衡大小(1个Ko的7个文件和1个Go的1个文件)引起的。
最后很难在不确切知道你的工作的情况下解释你的时间与CPU,但可能的解释是你有一个数据密集型工作(而不是CPU密集型工作),因此瓶颈是硬盘(SSD)在具有最慢CPU的机器上)。
答案 1 :(得分:0)
我终于设法解决了这个问题。这个小虫非常愚蠢而且显而易见,但是我花了很长时间才搞清楚......
正如我之前提到的,我不是从文件中读取输入,而是从 1网络开始生成输入,然后我在该网络上执行flatMap以获得N个网络,而不是获得N * M个新网络等等。
但是因为我从一个网络开始,当我做
时List<Network> data = Arrays.asList(new Network());
JavaRDD<Network> currentN = sc.parallelize(data);
数据在一个任务中仅在一个CPU上并行化,因为RDD只包含1个元素,因此存在问题。