【问题标题】:Spark,Graphx program does not utilize cpu and memorySpark,Graphx程序不使用cpu和内存
【发布时间】:2017-01-30 16:06:45
【问题描述】:

我有一个函数,它采用节点的邻居,对于邻居我使用广播变量和节点本身的 id,它计算该节点的接近中心性。我用结果映射图的每个节点那个功能。当我打开任务管理器时,cpu根本没有被利用,好像它没有并行工作一样,内存也是如此,但是每个节点都并行执行该功能,而且数据很大,需要时间完成,它不像不需要资源。每一个帮助都非常感谢,谢谢。 为了加载图表,我使用val graph = GraphLoader.edgeListFile(sc, path).cache

object ClosenessCentrality {

  case class Vertex(id: VertexId)

  def run(graph: Graph[Int, Float],sc: SparkContext): Unit = {
    //Have to reverse edges and make graph undirected because is bipartite
    val neighbors = CollectNeighbors.collectWeightedNeighbors(graph).collectAsMap()
    val bNeighbors = sc.broadcast(neighbors)

    val result = graph.vertices.map(f => shortestPaths(f._1,bNeighbors.value))
    //result.coalesce(1)
    result.count()

  }

  def shortestPaths(source: VertexId,  neighbors: Map[VertexId, Map[VertexId, Float]]): Double ={
    val predecessors = new mutable.HashMap[VertexId, ListBuffer[VertexId]]()
    val distances = new mutable.HashMap[VertexId, Double]()
    val q = new FibonacciHeap[Vertex]
    val nodes = new mutable.HashMap[VertexId, FibonacciHeap.Node[Vertex]]()

    distances.put(source, 0)

    for (w <- neighbors) {
      if (w._1 != source)
        distances.put(w._1, Int.MaxValue)

      predecessors.put(w._1, ListBuffer[VertexId]())
      val node = q.insert(Vertex(w._1), distances(w._1))
      nodes.put(w._1, node)
    }

    while (!q.isEmpty) {
      val u = q.minNode
      val node = u.data.id
      q.removeMin()
      //discover paths
      //println("Current node is:"+node+" "+neighbors(node).size)
      for (w <- neighbors(node).keys) {
        //print("Neighbor is"+w)
        val alt = distances(node) + neighbors(node)(w)
//        if (distances(w) > alt) {
//          distances(w) = alt
//          q.decreaseKey(nodes(w), alt)
//        }
//        if (distances(w) == alt)
//          predecessors(w).+=(node)
         if(alt< distances(w)){
           distances(w) = alt
           predecessors(w).+=(node)
           q.decreaseKey(nodes(w), alt)
         }

      }//For
    }
    val sum = distances.values.sum
    sum
  }

【问题讨论】:

  • 您是在集群还是本地启动程序?如果是本地主机,您是否指定了要使用的核心数,例如:--master=local[8]。或者,您的数据集有多少个分区?如果它只有一个分区,则使用单个核心。
  • 是的,我使用其他程序使用了更多资源。对于分区,我保留了从边缘列表文件加载图形时的默认值,但我想到了这一点,我使用了 coalesce我有 10 个 8 个内核,我应该使用更多还是我做错了;
  • 你能提供一些代码吗?
  • 感谢您的代码。奇怪的是,您不使用 GraphX 中的任何方法来处理图形。诸如计算最短路径之类的事情应该使用 Pregel API 来完成。此外,在您的第一个指令中,您似乎正在将 graoh 的整个邻接部分收集到驱动程序上。这是火花的一大“代码气味”。我知道这并不能真正回答问题,但您可能希望更改解决问题的方法以更好地利用 Spark 的分布式特性。
  • Graphx 提供 Pregel API 来计算图节点的 SSSP,这对我来说是相同的,但是你不能为每个节点并行执行此操作,就像使用它自己的图一样节点并行。我还没有想到更好的东西。起初我虽然相同,因为找到所有邻居几乎和图一样大,这不好但我不知道如何并行。

标签: apache-spark spark-graphx


【解决方案1】:

为了对您的原始问题提供一些答案,我怀疑您的 RDD 只有一个分区,因此使用单个核心来处理。

edgeListFile 方法有一个参数来指定您想要的最小分区数。 另外,您可以使用repartition 来获取更多分区。

您提到了coalesce,但默认情况下只会减少分区数量,请​​参阅此问题:Spark Coalesce More Partitions

【讨论】:

  • 谢谢你现在它可以工作了,但是我如何根据cpu的核心数来选择它;
  • 至少,您应该拥有与核心一样多的分区。但我强烈建议您使用更多,以确保每个分区足够小(特别是如果您希望每个顶点都跟踪整个图形)。我的建议是:tet,测试和更多测试,看看你是否能找到一个甜蜜点。
  • 就像一个sidenode:减小每个分区的大小(从而增加分区的数量)似乎不是100%的正确方法案例。每个分区的开销太大而无法忽略,因此请确保在它们之间取得平衡。无论如何,测试(和更多测试)建议对于中小型工作来说已经足够了。
猜你喜欢
  • 1970-01-01
  • 2018-06-21
  • 1970-01-01
  • 2015-10-26
  • 1970-01-01
  • 2017-05-29
  • 2011-06-24
  • 2017-08-30
  • 2016-01-25
相关资源
最近更新 更多