我想我有一个初学者的错误,但我真的不知道如何修复它,它把我逼疯了。我有一个由两台机器组成的集群:
8gbram(6.9可用),4核,win10:运行一个主进程,一个工作进程,它也是我运行java驱动程序的机器(来自intellij)
2gb内存(1.3可用),4核,虚拟机上的Ubuntu16.04(在vbox中运行):运行一个工作进程
我有一个类网络,我想在for循环中生成网络,从一个网络列表开始,然后使用flatmap将每个网络转换成n个新的网络。在那之后我有一个过滤器和一个计数。步骤:
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分钟
我的spark用户界面截图:
活着的工人
首次运行的事件时间线(使用两台机器):
按执行者聚合度量(使用两台机器)
我不知道为什么在虚拟机中运行ubuntu的机器比主机(主程序、工作程序和驱动程序)快,因为主机有更好的cpu(i7 2.6ghz比i3 1.9ghz)。
但是主要的问题是为什么在一台机器上运行要比在两台机器上运行快?不是应该反过来吗?我猜rdd不是并行计算的。如果是这样的话,你能解释一下我为什么和怎样才能使它并行处理吗?
工作内容说明:
基本上,这就是我想在for循环中实现的:
我从RDD1network开始(它不是一个文件,只是一个小类)。
在for循环中,我使用flatmap将1个网络转换成10个新网络。
迭代0:currentn=1网络->平面图->currentn=10网络
迭代1:currentn=10网络->平面图->currentn=100网络
. .
迭代9:currentn=10^8网络->平面图->currentn=10^9网络
如我所说,我正在生成输入。我想并行生成,这意味着平面图需要并行生成。为此,spark应:
以n网络的rdd为例
为每个核心将rdd划分为8个分区,每个分区有n/8个网络
在每台机器上并行应用flatmap,将每个n/8网络转换成n/8*10个新网络。
在每台机器上重复这些步骤,并行使用flatmap生成。
for循环结束后,每台机器应该有10^9/8个网络。并行过滤它们,然后计算每台机器上每个rdd中的元素数,并输出答案。
这是我想要实现的,但是由于某些原因,for循环中的flatmap生成只在一台机器上完成。
2条答案
按热度按时间cqoc49vn1#
我终于解决了这个问题。这个错误是如此愚蠢和明显,但我花了这么长时间才弄明白。。。
如前所述,我不是从文件中读取输入,而是从1个网络开始生成输入,然后在该网络上进行平面Map,得到n个网络,然后得到n*m个新网络,以此类推。
但因为我只从一个网络开始,当我
在一个任务中,数据只能在一个cpu上并行化,因为rdd只包含1个元素,因此出现了问题。
fdbelqdn2#
spark ui的最后一个屏幕截图显示,在您的8个任务中,7个任务以37毫秒的最长时间完成,而最长的任务至少运行了46秒。
如果您有一个任务运行3分钟,而其他任务运行不到一秒钟,那么您的分布式计算是不平衡的,因此您无法利用多台计算机同时运行的优势,因为计算时间受最长任务的限制。
这种行为通常是由大小不平衡的输入(7个1 ko文件和1个1 go文件)或不平衡的操作/转换引起的(
join
, ...).最后,在不确切知道自己的工作是什么的情况下很难解释时间与cpu的关系,但一个可能的解释是,您有一个数据密集型工作(而不是cpu密集型工作),因此瓶颈是硬盘驱动器(cpu最慢的机器上的ssd)。