java - 无向图DFS的并行实现

标签 java multithreading performance algorithm parallel-processing

我一直在尝试在 Java 中为无向图实现并行深度优先搜索。我写了这段代码,但它不能正常工作。它不会加速。

主要方法:

 package dfsearch_v2;

 import java.util.Calendar;
 import java.util.Stack;
 import java.util.Random;

 public class DFSearch_v2 {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {

    long ts_b, ts_e;
    int el_count=100;
    int thread_count = 4;
    int vertices[][]; // graph matrix
    boolean isVisited[] = new boolean[el_count];
    for(int i=0;i<el_count;i++){
        for(int j=0;j<el_count;j++){
            Random boolNumber = new Random();
            boolean edge = boolNumber.nextBoolean(); 
            vertices[i][j]=edge ? 1 : 
        }   
    }


    DFSTest r[] = new DFSTest[thread_count];
    ts_b = Calendar.getInstance().getTimeInMillis();
    for(int i = 0; i < thread_count; i++) {
        r[i] = new DFSTest(el_count,vertices,isVisited);
        r[i].start();
    }

    for(int i = 0; i < thread_count;    
        try {   
            r[i].join();
          } catch (InterruptedException e) {

          }
    }
    ts_e = Calendar.getInstance().getTimeInMillis();
    System.out.println("Time "+(ts_e-ts_b));      
}

线程实现:

package dfsearch_v2;

import java.util.Stack;

public class DFSTest extends Thread {

    int numberOfNodes;
    int adj[][];
    boolean isVisit[];



public DFSTest(int numberOfNodes, int adj[][],boolean isVisit[]){
    this.numberOfNodes = numberOfNodes;
    this.adj=adj;  
    this.isVisit=isVisit;
}

public void run()
{
    int k,i,s=0;
    Stack<Integer> st = new Stack<>();
    for(k=0; k < numberOfNodes; k++) isVisit[k]=false;
    for (k = numberOfNodes - 1; k >= 0; k--) {
        st.push(k);
    }
        DFSearch(st, isVisit);


}

   private void DFSearch(Stack<Integer> st,boolean isVisit[]){
       synchronized(isVisit){
        int i,k;
        while (!st.empty()) { 
        k=st.pop();
        if (!isVisit[k]) {
            isVisit[k] = true;
            System.out.println("Node "+k+" is visit");

            for(i=numberOfNodes-1; i>=0; i--)
                if(adj[k][i]==1) st.push(i);
        }

    }

  }

 }


}

请问有人能帮帮我吗?我真的是并行编程的新手。

谢谢

最佳答案

如果我正确理解您的程序,您将锁定在所有线程之间共享的 isVisit 数组 - 这意味着您不会获得任何加速,因为只有一个线程能够取得进展。尝试使用 ConcurrentHashMapConcurrentSkipListMap相反。

// shared between all threads
ConcurrentMap<Integer, Boolean> map = new ConcurrentHashMap<>();

public boolean isVisit(Integer integer) {
    return map.putIfAbsent(integer, Boolean.TRUE) != null;
}

private void DFSearch(Stack<Integer> st) {
    if(!isVisit(st.pop())) {
       ...
    }
}

并发 map 使用分片来增加并行度。在 isVisit 中使用 putIfAbsent 方法来避免数据竞争(您只希望该方法为一个线程返回 false)。

至于如何在多个线程之间分配工作,请使用工作线程的 ConcurrentLinkedQueue。当一个线程没有更多的工作要执行时,它会将自己添加到工作线程队列中。当一个线程有两条边要遍历时,它会轮询工作线程队列以寻找可用的工作线程,如果有可用的,它会将其中一条边分配给工作线程。当所有线程都在可用线程队列中时,您就遍历了整个列表。

关于java - 无向图DFS的并行实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16927303/

相关文章:

ruby - Ruby pre-1.9 和 Ruby 1.9 线程之间有什么实际区别吗?

java - Spring RESTful Web 服务 + AngularJS HTTP 404 错误

java - 如果字符串包含在括号中,请将其删除

c++ - 这个 boost::asio 和 boost::coroutine 使用模式有什么问题?

python - Web.py:无法通过多个浏览器选项卡获得多线程行为

android - 如何以编程方式启用和禁用振动模式

c# - foreach + break vs linq FirstOrDefault 性能差异

performance - Maven中有 "skip weaving flag"吗? (不包括 AspectJ)

java - 调整标签大小以适合内容

java - 如何在 fragment 中隐藏工具栏?