从并发到并行处理的步调

时间:2015-10-15 04:40:31

标签: java multithreading

我有一个四核cpu,我出于性能原因试图尝试多线程。我已经在下面编写了这段代码,只是为了看看它的速度有多快,而且我注意到它实际上比只使用主线程的第二个代码块慢了

int numCrunchers = Runtime.getRuntime().availableProcessors();
public void crunch() {
    int numPairs = 1000;

    for(int i=0; i < numPairs; i++)
        pairs.add(...);

    int share = pairs.size()/numCrunchers;

    for(int i=0; i < numCrunchers; i++) {
        Cruncher cruncher = crunchers.get(i);

        for(int j=0; j < share; j++)
            cruncher.nodes.add(pairs.poll());
    }

    for(Cruncher cruncher : crunchers)
        threadpool.execute(cruncher);

    threadpool.shutdown();

    try {
        threadpool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

private class Cruncher implements Runnable {
    public BlockingQueue<Pair<PathNode>> nodes = new LinkedBlockingQueue<Pair<PathNode>>();
    private AStarPathfinder pathfinder;
    private LinkedList<PathNode> path = new LinkedList<PathNode>();

    public Cruncher(GridGraph graph) {
        pathfinder = new AStarPathfinder(graph);
    }

    @Override
    public void run() {
        while(true) {
            path.clear();
            Pair<PathNode> pair = nodes.poll();
            if(pair != null) {
                pathfinder.search(path, pair.first(), pair.second());
                paths.add(new LinkedList<PathNode>(path));
            } else {
                System.out.println("This cruncher is done");
                break;
            }
        }
    }
}

每个线程在我的电脑上花费了大约34,000,000,000纳秒,但是当我决定使用除主线程之外没有线程时,它只需要1,090,195,046纳秒,34倍的时差。

    LinkedList<Pair<PathNode>> pairs = new LinkedList<Pair<PathNode>>();
    int numPairs = 1000;
    AStarPathfinder pathfinder = new AStarPathfinder(graph);

    for(int i=0; i < numPairs; i++)
        pairs.add(...);

    long current = System.nanoTime();
    for(int i=0; i < numPairs; i++) {
        Pair<PathNode> pair = pairs.poll();
        path.clear();
        pathfinder.search(path, pair.first(), pair.second());
    }
    System.out.printf("Operation took %d nanoseconds", System.nanoTime() - current);

我的问题是为什么使用多个线程导致程序运行缓慢?代码是不是正确地利用了我的cpu上的所有内核?我运行了几次,结果相似,(30+)x多线程和单线程之间的时差

修改: 决定测量多线程上每个单独操作的时间

    while(true) {
        path.clear();
        Pair<PathNode> pair = nodes.poll();
        if(pair != null) {
            long current = System.nanoTime();
            pathfinder.search(path, pair.first(), pair.second());
            paths.add(new LinkedList<PathNode>(path));
            System.out.printf("Took %d nanoseconds\n", System.nanoTime() - current);
        } else {
            System.out.println("This cruncher is done");
            break;
        }
    }

和单线程...

    LinkedList<Pair<PathNode>> pairs = new LinkedList<Pair<PathNode>>();
    int numPairs = 1000;
    AStarPathfinder pathfinder = new AStarPathfinder(graph);

    for(int i=0; i < numPairs; i++)
        pairs.add(...);

    for(int i=0; i < numPairs; i++) {
        long current = System.nanoTime();
        Pair<PathNode> pair = pairs.poll();
        path.clear();
        pathfinder.search(path, pair.first(), pair.second());
        System.out.printf("Operation took %d nanoseconds", System.nanoTime() - current);
    }

每个Cruncher都有自己的AStarPathfinder实例,因此pathfinder.search()无法在每个线程之间造成阻塞。多线程应用程序仍然慢得多。

0 个答案:

没有答案