简体   繁体   English

线程不会比没有线程版本快多少

[英]Threads not much faster than no thread version

I know there are other questions like that but I'm a beginner and most of the code and questions were quite complicated. 我知道还有其他类似的问题,但是我是一个初学者,大多数代码和问题都非常复杂。 Thats why I keep it as simple as possible. 这就是为什么我让它尽可能简单。 I come from an R background but recently I wanted to learn more about Java threads. 我来自R的背景,但是最近我想了解有关Java线程的更多信息。 I run through several tutorial on the topic and most of it boils down to the code I posted below. 我完成了有关该主题的几个教程,其中大部分都归结为我在下面发布的代码。 Note the code is not doing much and I made it quite inefficient so the threads would run a few seconds. 请注意,代码并没有做很多事情,我使它效率很低,因此线程将运行几秒钟。 The main thing to notice is that on my machine the threads run not much faster than the none threaded run. 需要注意的主要事情是,在我的计算机上,线程的运行速度比无线程运行的快。 With low values in the for loop in the run method even sometimes slower. 在run方法中,for循环中的值较低,有时甚至会更慢。 It could be because of my crappy hardware (only two cores), and that with more cores one would see the threads go faster than the non parallel version. 可能是因为我的硬件笨拙(只有两个内核),而且内核越多,线程运行速度就会比非并行版本快。 I don't know. 我不知道。 But what puzzles me most is that when I look at the System monitor while the program is running in both runs (parallel and non parallel) both cores are used but in the parallel version they run at nearly 100 % and in non parallel both run at 50 - 60 %. 但是,令我最困惑的是,当我在程序同时运行(并行和非并行)运行时查看系统监视器时,两个内核都被使用,但是在并行版本中,它们以接近100%的速度运行,而在非并行中两个内核都以50-60%。 Considering that both finish at the same time the parallel version is a lot more inefficient because it uses more computer power for doing the same job not even faster. 考虑到两个版本同时完成,并行版本的效率要低得多,因为它使用更多的计算机功能来完成相同的工作甚至没有更快。 To put it in the nutshell. 简而言之。 What am I doing wrong? 我究竟做错了什么? I thought I wrote the the program not much different than in the Java tutorial. 我以为我编写的程序与Java教程没什么不同。 I posted the link below. 我在下面发布了链接。 I run linux ubuntu with the sun version of java. 我使用Java的Sun版本运行linux ubuntu。

http://www.java2s.com/Tutorial/Java/0160__Thread/0020__Create-Thread.htm http://www.java2s.com/Tutorial/Java/0160__Thread/0020__Create-Thread.htm

import java.util.ArrayList;

public class Main { 
    public static void main(String[] args) {
        ArrayList<PermutateWord> words = new ArrayList<PermutateWord>();
        System.out.println(Runtime.getRuntime().availableProcessors());
        for(int i = 0; i < Runtime.getRuntime().availableProcessors();i++){
            words.add(new PermutateWord("Christoph"));
        }
        System.out.println("Run as thread");
        long d = System.currentTimeMillis();
        for (PermutateWord w : words) {
            w.start();
        }
        for (PermutateWord w : words) {
            try {
                w.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for (PermutateWord w : words) {
            System.out.println(w.getWord());
        }
        System.out.println(((double)(System.currentTimeMillis()-d))/1000+"\n");
        System.out.println("No thread");
        d = System.currentTimeMillis();
        for (PermutateWord w : words) {
            w.run();
        }
        for (PermutateWord w : words) {
            System.out.println(w.getWord());
        }
        System.out.println(((double)(System.currentTimeMillis()-d))/1000+"\n");
    }
}
class PermutateWord extends Thread {    
    private String word;
    public PermutateWord (String word){
        this.word = word;
    }
    public void run() {
        java.util.Random rand = new java.util.Random();
        for(int i = 0; i <8000000;i++){
            word = swap(word,rand.nextInt(word.length()), rand.nextInt(word.length()));
        }
    }
    private String swap(String word2, int r1, int r2) {
        char[] wordArray = word2.toCharArray();
        char c = wordArray[r1];
        wordArray[r1] = wordArray[r2];
        wordArray[r2] = c;
        return new String(wordArray);
    }
    public String getWord(){
        return word;
    }
}

Thanks in advance 提前致谢

Christoph 克里斯多夫

Most of the time is spend allocating and dealocating temporary strings, which has to be synchronized. 大多数时间是花在分配和取消分配必须同步的临时字符串上。 The work that can be done in parallel is trivial and multiple threads won't give you much gain. 可以并行完成的工作是微不足道的,并且多个线程不会给您带来太大的收益。

Math.random() also has to be synchronized. Math.random()也必须同步。 You will have better results creating local java.util.Random for each thread. 为每个线程创建本地java.util.Random会得到更好的结果。

java.util.Random rand = new java.util.Random();

public void run() {
    for(int i = 0; i <8000000;i++){
        word = swap(word,rand.nextInt(word.length()), rand.nextInt(word.length()));
    }
}

But, you should really focus on optimizing swap function. 但是,您应该真正专注于优化swap功能。 I'm not sure, if it does what you want, but I'm sure it's very inefficient. 我不确定它是否可以满足您的要求,但是我确定它的效率很低。 + is expensive operation on String s. +是对String昂贵的操作。 For every + JVM has to allocate new String which is slow and doesn't work well with multiple threads. 对于每个+ JVM,JVM都必须分配新的String ,这很慢并且不能与多个线程一起很好地工作。 If you just want to swap two characters, consider using char[] instead of String . 如果只想交换两个字符,请考虑使用char[]而不是String It should be much easier and much faster. 它应该更容易,更快。

edit: 编辑:

private String swap(String word2, int r1, int r2) {
    char[] wordArray = word2.toCharArray();
    char c = wordArray[r1];
    wordArray[r1] = wordArray[r2];
    wordArray[r2] = c;
    return new String(wordArray);
}

This is much better. 这样好多了。 However, you are still doing 2 allocations. 但是,您仍在进行2个分配。 toCharArray() and new String both allocate memory. toCharArray()new String都分配内存。 Because rest of your program is very simple, those two allocations take 90% of your execution time. 因为程序的其余部分非常简单,所以这两个分配占用了90%的执行时间。

I got a lot of mileage out of putting a Thread.sleep(1000) in the join loop. 通过将Thread.sleep(1000)放入联接循环,我获得了很多收获。 Empirically, java.util.Random.nextFloat() only bought me 10%. 根据经验,java.util.Random.nextFloat()只给我买了10%。

Even then, both parts ran in 16 seconds on an 8-core machine, suggesting it's serializing due to the synchronizations mentioned above. 即使那样,这两部分都在一台8核计算机上运行了16秒,这表明由于上述同步,它正在序列化。 But good, grief, without the sleep it was running 10x slower. 但是,好,悲伤,没有睡眠,它的运行速度慢了十倍。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM