Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用java中的线程优化程序_Java_Multithreading_Binary Tree - Fatal编程技术网

用java中的线程优化程序

用java中的线程优化程序,java,multithreading,binary-tree,Java,Multithreading,Binary Tree,我的目标是使用Java中的ExecutorService计算二叉树中的元素总数,然后使用CompletionService收集每个任务的结果 用户给出树的高度、并行性开始的级别以及要使用的线程数。我知道,ExecutorService应该产生与用户给定的线程数完全相同的线程,而完成服务应该在preProcess方法中产生正好N个任务,其中N是2^(并行级别),因为在某个级别上,N,我们将有2^N个节点 我的问题是,我不知道如何从给定高度开始遍历树,以及如何使用CompletionService在

我的目标是使用Java中的
ExecutorService
计算二叉树中的元素总数,然后使用
CompletionService
收集每个任务的结果

用户给出树的高度、并行性开始的级别以及要使用的线程数。我知道,
ExecutorService
应该产生与用户给定的线程数完全相同的线程,而完成服务应该在
preProcess
方法中产生正好N个任务,其中N是2^(并行级别),因为在某个级别上,N,我们将有2^N个节点

我的问题是,我不知道如何从给定高度开始遍历树,以及如何使用
CompletionService
在我的
postProcess
方法中收集结果。此外,每次生成新任务时,总任务数将增加一个,而每次
CompletionService
返回结果时,任务数应减少一个

我能够在
processTreeParallel
函数中使用
CompletionService
,但我真的不明白如何在
postProcess
方法中使用它

这是我的密码:

import java.util.concurrent.*;

public class TreeCalculation {
    // tree level to go parallel
    int levelParallel;
    // total number of generated tasks
    long totalTasks;
    // current number of open tasks
    long nTasks;
    // total height of tree
    int height;
    // Executors
    ExecutorService exec;
    CompletionService<Long> cs;
    TreeCalculation(int height, int levelParallel) {
        this.height = height;
        this.levelParallel = levelParallel;
    }

    void incrementTasks() {
        ++nTasks;
        ++totalTasks;
    }

    void decrementTasks() {
        --nTasks;
    }

    long getNTasks() {
        return nTasks;
    }
    // Where the ExecutorService should be initialized 
    // with a specific threadCount
    void preProcess(int threadCount) {

        exec = Executors.newFixedThreadPool(threadCount);
        cs = new ExecutorCompletionService<Long>(exec);
        nTasks = 0;
        totalTasks = 0;
    }
    // Where the CompletionService should collect the results;
    long postProcess() {
        long result = 0;
        return result;
    }

    public static void main(String[] args) {
        if (args.length != 3) {
            System.out.println(
                "usage: java Tree treeHeight levelParallel nthreads\n");
            return;
        }
        int height = Integer.parseInt(args[0]);
        int levelParallel = Integer.parseInt(args[1]);
        int threadCount = Integer.parseInt(args[2]);

        TreeCalculation tc = new TreeCalculation(height, levelParallel);

        // generate balanced binary tree
        Tree t = Tree.genTree(height, height);

        //System.gc();

        // traverse sequential
        long t0 = System.nanoTime();
        long p1 = t.processTree();
        double t1 = (System.nanoTime() - t0) * 1e-9;

        t0 = System.nanoTime();
        tc.preProcess(threadCount);
        long p2 = t.processTreeParallel(tc);
        p2 += tc.postProcess();
        double t2 = (System.nanoTime() - t0) * 1e-9;

        long ref = (Tree.counter * (Tree.counter + 1)) / 2;
        if (p1 != ref)
            System.out.printf("ERROR: sum %d != reference %d\n", p1, ref);
        if (p1 != p2)
            System.out.printf("ERROR: sum %d != parallel %d\n", p1, p2);
        if (tc.totalTasks != (2 << levelParallel)) {
            System.out.printf("ERROR: ntasks %d != %d\n", 
                2 << levelParallel, tc.totalTasks);
        }

        // print timing
        System.out.printf("tree height: %2d "
            + "sequential: %.6f "
            + "parallel with %3d threads and %6d tasks: %.6f  "
            + "speedup: %.3f count: %d\n",
            height, t1, threadCount, tc.totalTasks, t2, t1 / t2, ref);
    }
}

// ============================================================================

class Tree {

    static long counter; // counter for consecutive node numbering

    int level; // node level
    long value; // node value
    Tree left; // left child
    Tree right; // right child

    // constructor
    Tree(long value) {
        this.value = value;
    }

    // generate a balanced binary tree of depth k
    static Tree genTree(int k, int height) {
        if (k < 0) {
            return null;
        } else {
            Tree t = new Tree(++counter);
            t.level = height - k;
            t.left = genTree(k - 1, height);
            t.right = genTree(k - 1, height);
            return t;
        }
    }

    // ========================================================================
    // traverse a tree sequentially

    long processTree() {
        return value
            + ((left == null) ? 0 : left.processTree())
            + ((right == null) ? 0 : right.processTree());
    }

    // ========================================================================
    // traverse a tree parallel
    // This is where I was able to use the CompletionService
    long processTreeParallel(TreeCalculation tc) {

        tc.totalTasks = 0;
        for(long i =0; i<(long)Math.pow(tc.levelParallel, 2); i++)
        {
            tc.incrementTasks();
            tc.cs.submit(new Callable<Long>(){
                @Override
                public Long call() throws Exception {
                    return processTree();
                }

            });
        }
        Long result = Long.valueOf(0);
        for(int i=0; i<(long)Math.pow(2,tc.levelParallel); i++) {
            try{
                result += tc.cs.take().get();
                tc.decrementTasks();
            }catch(Exception e){}

        }
        return result;
    }
}
import java.util.concurrent.*;
公共类树计算{
//树级并行
int-levelParallel;
//生成的任务总数
长期任务;
//当前打开的任务数
长的三角帆;
//树的总高度
内部高度;
//遗嘱执行人
服务执行人;
完成服务cs;
树计算(整数高度,整数水平平行){
高度=高度;
this.levelParallel=levelParallel;
}
void incrementTasks(){
++nTasks;
++总体任务;
}
无效递减任务(){
--nTasks;
}
long getNTasks(){
返回NTASK;
}
//其中应初始化ExecutorService
//具有特定的线程数
void预处理(int threadCount){
exec=Executors.newFixedThreadPool(线程计数);
cs=新的ExecutorCompletionService(exec);
nTasks=0;
totalTasks=0;
}
//CompletionService应在何处收集结果;
长后处理(){
长结果=0;
返回结果;
}
公共静态void main(字符串[]args){
如果(参数长度!=3){
System.out.println(
“用法:java树树高级别并行读取\n”);
返回;
}
int height=Integer.parseInt(args[0]);
int-levelParallel=Integer.parseInt(args[1]);
int threadCount=Integer.parseInt(args[2]);
TreeCalculation tc=新的TreeCalculation(高度、水平平行);
//生成平衡二叉树
Tree t=Tree.genTree(高度,高度);
//gc();
//遍历顺序
long t0=System.nanoTime();
长p1=t.processTree();
双t1=(System.nanoTime()-t0)*1e-9;
t0=系统。纳米时间();
tc.预处理(线程数);
长p2=t.processTreeParallel(tc);
p2+=tc.postProcess();
双t2=(System.nanoTime()-t0)*1e-9;
long ref=(Tree.counter*(Tree.counter+1))/2;
如果(p1!=参考)
System.out.printf(“错误:总和%d!=引用%d\n”,p1,ref);
如果(p1!=p2)
System.out.printf(“错误:和%d!=并行%d\n”,p1,p2);

如果(tc.totalTasks!=(2我假设您希望通过并行运行计算的不同部分来加速“树处理”任务

据我所知,您当前的解决方案提交了多个可调用项,每个可调用项执行完全相同的操作,即每个进程执行整个树。这意味着您多次执行相同的总体任务。这不太可能是您想要的。相反,您可能希望将总体任务拆分为多个部分任务。部分任务s应不重叠,并且一起覆盖整个任务。对于这些部分任务,您可以并行执行,并以某种方式收集结果

由于您是在树上执行,因此必须找到某种方法将树的处理划分为适当的部分。最好是以更易于设计和实现的方式,以及使用大部分大小合适的块,以便并行化更有效

当前的并行计算也是错误的,从使用以下输入运行程序可以看出:

java TreeCalculation 10 2 4
Math.pow(tc.levelParallel,2)
Math.pow(2,tc.levelParallel)
的调用也不同


还要注意内存一致性问题。我一眼就看不到任何问题,尽管你确实在这里和那里变异内存。

这里的基本思想是,你遍历树,并像你在
processTree
方法中那样计算结果。但是一旦达到了并行计算应该开始的级别(在
levelParallel
)中,您只需生成一个实际在内部调用
processTree
的任务。这将处理树的其余部分

processTreeParallel             0
                               / \    
                              /   \    
processTreeParallel          1     2
                            / \   / \    
processTreeParallel        3   4 5   6  <- levelParallel
                           |   | |   |
processTree call for each: v   v v   v
                          +---------------+
tasks for executor:       |T   T T   T    |
                          +---------------+
completion service         |
fetches tasks and          v
sums them up:              T+T+T+T  -> result
完整的程序如下所示:

import java.util.concurrent.*;

public class TreeCalculation
{
    // tree level to go parallel
    int levelParallel;
    // total number of generated tasks
    long totalTasks;
    // current number of open tasks
    long nTasks;
    // total height of tree
    int height;
    // Executors
    ExecutorService exec;
    CompletionService<Long> cs;

    TreeCalculation(int height, int levelParallel)
    {
        this.height = height;
        this.levelParallel = levelParallel;
    }

    void incrementTasks()
    {
        ++nTasks;
        ++totalTasks;
    }

    void decrementTasks()
    {
        --nTasks;
    }

    long getNTasks()
    {
        return nTasks;
    }

    // Where the ExecutorService should be initialized
    // with a specific threadCount
    void preProcess(int threadCount)
    {
        exec = Executors.newFixedThreadPool(threadCount);
        cs = new ExecutorCompletionService<Long>(exec);
        nTasks = 0;
        totalTasks = 0;
    }

    // Where the CompletionService should collect the results;
    long postProcess()
    {
        exec.shutdown();
        long result = 0;
        for (int i = 0; i < (long) Math.pow(2, levelParallel); i++)
        {
            try
            {
                result += cs.take().get();
                decrementTasks();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        return result;
    }

    public static void main(String[] args)
    {

        int height = 22;
        int levelParallel = 3;
        int threadCount = 4;
        if (args.length != 3)
        {
            System.out.println(
                "usage: java Tree treeHeight levelParallel nthreads\n");
            System.out.println("Using default values for test");
        }
        else
        {
            height = Integer.parseInt(args[0]);
            levelParallel = Integer.parseInt(args[1]);
            threadCount = Integer.parseInt(args[2]);

        }

        TreeCalculation tc = new TreeCalculation(height, levelParallel);

        // generate balanced binary tree
        Tree t = Tree.genTree(height, height);

        // traverse sequential
        long t0 = System.nanoTime();
        long p1 = t.processTree();
        double t1 = (System.nanoTime() - t0) * 1e-9;

        t0 = System.nanoTime();
        tc.preProcess(threadCount);
        long p2 = t.processTreeParallel(tc);
        p2 += tc.postProcess();
        double t2 = (System.nanoTime() - t0) * 1e-9;

        long ref = (Tree.counter * (Tree.counter + 1)) / 2;
        if (p1 != ref)
            System.out.printf("ERROR: sum %d != reference %d\n", p1, ref);
        if (p1 != p2)
            System.out.printf("ERROR: sum %d != parallel %d\n", p1, p2);
        if (tc.totalTasks != (1 << levelParallel))
        {
            System.out.printf("ERROR: ntasks %d != %d\n", 1 << levelParallel,
                tc.totalTasks);
        }

        // print timing
        System.out.printf("tree height: %2d\n" 
            + "sequential: %.6f\n"
            + "parallel with %3d threads and %6d tasks: %.6f\n"
            + "speedup: %.3f count: %d\n",
            height, t1, threadCount, tc.totalTasks, t2, t1 / t2, ref);
    }
}

// ============================================================================

class Tree
{

    static long counter; // counter for consecutive node numbering

    int level; // node level
    long value; // node value
    Tree left; // left child
    Tree right; // right child

    // constructor
    Tree(long value)
    {
        this.value = value;
    }

    // generate a balanced binary tree of depth k
    static Tree genTree(int k, int height)
    {
        if (k < 0)
        {
            return null;
        }

        Tree t = new Tree(++counter);
        t.level = height - k;
        t.left = genTree(k - 1, height);
        t.right = genTree(k - 1, height);
        return t;
    }

    // ========================================================================
    // traverse a tree sequentially

    long processTree()
    {
        return value 
            + ((left == null) ? 0 : left.processTree())
            + ((right == null) ? 0 : right.processTree());
    }

    // ========================================================================
    // traverse a tree parallel
    long processTreeParallel(TreeCalculation tc)
    {
        if (level < tc.levelParallel)
        {
            long leftResult = left.processTreeParallel(tc);
            long rightResult = right.processTreeParallel(tc);
            return value + leftResult + rightResult;
        }
        tc.incrementTasks();
        tc.cs.submit(new Callable<Long>()
        {
            @Override
            public Long call() throws Exception
            {
                return processTree();
            }
        });
        return 0;
    }
}
import java.util.concurrent.*;
公共类树计算
{
//树级并行
int-levelParallel;
//生成的任务总数
长期任务;
//当前打开的任务数
长的三角帆;
//树的总高度
内部高度;
//遗嘱执行人
服务执行人;
完成服务cs;
树计算(整数高度,整数水平平行)
{
高度=高度;
this.levelParallel=levelParallel;
}
void incrementTasks()
{
++nTasks;
++总体任务;
}
无效递减任务()
{
--nTasks;
}
long getNTasks()
{
import java.util.concurrent.*;

public class TreeCalculation
{
    // tree level to go parallel
    int levelParallel;
    // total number of generated tasks
    long totalTasks;
    // current number of open tasks
    long nTasks;
    // total height of tree
    int height;
    // Executors
    ExecutorService exec;
    CompletionService<Long> cs;

    TreeCalculation(int height, int levelParallel)
    {
        this.height = height;
        this.levelParallel = levelParallel;
    }

    void incrementTasks()
    {
        ++nTasks;
        ++totalTasks;
    }

    void decrementTasks()
    {
        --nTasks;
    }

    long getNTasks()
    {
        return nTasks;
    }

    // Where the ExecutorService should be initialized
    // with a specific threadCount
    void preProcess(int threadCount)
    {
        exec = Executors.newFixedThreadPool(threadCount);
        cs = new ExecutorCompletionService<Long>(exec);
        nTasks = 0;
        totalTasks = 0;
    }

    // Where the CompletionService should collect the results;
    long postProcess()
    {
        exec.shutdown();
        long result = 0;
        for (int i = 0; i < (long) Math.pow(2, levelParallel); i++)
        {
            try
            {
                result += cs.take().get();
                decrementTasks();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        return result;
    }

    public static void main(String[] args)
    {

        int height = 22;
        int levelParallel = 3;
        int threadCount = 4;
        if (args.length != 3)
        {
            System.out.println(
                "usage: java Tree treeHeight levelParallel nthreads\n");
            System.out.println("Using default values for test");
        }
        else
        {
            height = Integer.parseInt(args[0]);
            levelParallel = Integer.parseInt(args[1]);
            threadCount = Integer.parseInt(args[2]);

        }

        TreeCalculation tc = new TreeCalculation(height, levelParallel);

        // generate balanced binary tree
        Tree t = Tree.genTree(height, height);

        // traverse sequential
        long t0 = System.nanoTime();
        long p1 = t.processTree();
        double t1 = (System.nanoTime() - t0) * 1e-9;

        t0 = System.nanoTime();
        tc.preProcess(threadCount);
        long p2 = t.processTreeParallel(tc);
        p2 += tc.postProcess();
        double t2 = (System.nanoTime() - t0) * 1e-9;

        long ref = (Tree.counter * (Tree.counter + 1)) / 2;
        if (p1 != ref)
            System.out.printf("ERROR: sum %d != reference %d\n", p1, ref);
        if (p1 != p2)
            System.out.printf("ERROR: sum %d != parallel %d\n", p1, p2);
        if (tc.totalTasks != (1 << levelParallel))
        {
            System.out.printf("ERROR: ntasks %d != %d\n", 1 << levelParallel,
                tc.totalTasks);
        }

        // print timing
        System.out.printf("tree height: %2d\n" 
            + "sequential: %.6f\n"
            + "parallel with %3d threads and %6d tasks: %.6f\n"
            + "speedup: %.3f count: %d\n",
            height, t1, threadCount, tc.totalTasks, t2, t1 / t2, ref);
    }
}

// ============================================================================

class Tree
{

    static long counter; // counter for consecutive node numbering

    int level; // node level
    long value; // node value
    Tree left; // left child
    Tree right; // right child

    // constructor
    Tree(long value)
    {
        this.value = value;
    }

    // generate a balanced binary tree of depth k
    static Tree genTree(int k, int height)
    {
        if (k < 0)
        {
            return null;
        }

        Tree t = new Tree(++counter);
        t.level = height - k;
        t.left = genTree(k - 1, height);
        t.right = genTree(k - 1, height);
        return t;
    }

    // ========================================================================
    // traverse a tree sequentially

    long processTree()
    {
        return value 
            + ((left == null) ? 0 : left.processTree())
            + ((right == null) ? 0 : right.processTree());
    }

    // ========================================================================
    // traverse a tree parallel
    long processTreeParallel(TreeCalculation tc)
    {
        if (level < tc.levelParallel)
        {
            long leftResult = left.processTreeParallel(tc);
            long rightResult = right.processTreeParallel(tc);
            return value + leftResult + rightResult;
        }
        tc.incrementTasks();
        tc.cs.submit(new Callable<Long>()
        {
            @Override
            public Long call() throws Exception
            {
                return processTree();
            }
        });
        return 0;
    }
}