【问题标题】:Parallel sieve of Eratosthenes - Java MultithreadingEratosthenes 的并行筛 - Java 多线程
【发布时间】:2013-09-03 21:04:42
【问题描述】:

我想写一个 Eratosthenes 筛子,它可以使用特定数量的线程。我发现,它将以下列方式工作: 对于 2 个线程,最多 17 个。 Thread-1 取 2,并开始从 List 中删除 2 的倍数。 Parallel Thread-2 需要 3 并且执行相同的操作。之后 Thread-1 需要 5(因为 List 中没有 4), Thread-2 需要 7 等等,直到它们结束。 我写了以下代码:

private List<Integer> array = new ArrayList<Integer>();
private List<Integer> results = new ArrayList<Integer>();
public synchronized void run(){
    while(array.size() > 0){
        Integer tmp = array.get(0);
        for(int i = 1; i < array.size(); i++){
            if( (array.get(i).intValue() % tmp.intValue()) == 0)
                array.remove(i);
        }
        results.add(array.get(0));
        array.remove(0);
    }
}

public void setArray(int x){
    for(int i = 2; i < x; i++)
        array.add(Integer.valueOf(i));
}
public void printArray(){
    for(Integer i: results){
        System.out.println(i);
    }
}

此代码有效,但我在我的主类中添加了时间测量“工具”:

ThreadTask task = new ThreadTask();
task.setArray(5000);
Long beg = new Date().getTime();
for(int i = 0; i < 3;i++){
    new Thread(task).start();
}
Long sleep = 1000L;
Thread.sleep(sleep);// I am sleeping main thread to wait until other Threads are done
task.printArray();
System.out.println("Time is "+(new Date().getTime()-beg-sleep));

问题是用 2 个线程运行这个比用 1 个线程运行慢,3 个线程比 2 个线程慢。谁能解释一下,为什么?

编辑:

关于这一点有一件很重要的事情。我不需要尽可能快地完成它。出于一个原因,我需要它在线程上工作。我的老师想比较运行同一程序与 1、2 .. n 线程的运行时间。结果应该类似于this 图表。

EDIT2:

我已将代码重写为以下

private HashMap<Integer,Boolean> array = new HashMap<Integer,Boolean>();
private int counter = 1;
private int x;
public void run(){
    while(counter < x-1){
        do{
            counter++;
        }
        while( array.get(counter));
        int tmp = counter;
        for(int i = tmp; i < array.size(); i+=tmp){
            if( i!= tmp)
                array.put(i,true);
        }
        try{
        Thread.sleep(0L, 1);
        }
        catch (Exception e){}
    }
}

public void setArray(int x){
    this.x = x;
    for(int i = 2; i < x; i++)
        array.put(i, false);
}
public void printArray(){

    for(int i = 2; i < array.size();i++){
        if( !array.get(i))
        System.out.println(i);

    }
}

现在它使用 HashMap,它是这样工作的:

  1. 用从 2 到 n 的键和假值填充 HashMap。
  2. 新线程进入基于counter 变量的while 循环。 Counter 代表当前密钥。
  3. 在乞求时增加计数器,这样新线程就不会在早先启动的线程的counter 上运行。
  4. counter值放入临时变量tmp,这样即使另一个线程增加counter我们也可以工作
  5. 通过将itmp 递增(实际上是在i 的倍数上跳跃)来迭代HashMap,并将它们的值设置为true
  6. 打印方法中忽略所有具有true 值的键。 counter 在增加时也会跳过它们。

问题是它仍然较慢有更多线程。现在怎么了?

【问题讨论】:

  • 您的运行方法是同步的,因此一次只能运行 1 个线程。
  • 如果 run 是您的 ThreadTask 的实际 run 方法,那么您的两个线程本质上是按顺序工作的,因为该方法是同步的,从而阻止线程并行工作(这是重点使用线程!)。
  • 我认为有问题...您说 Thread-1 需要 5,因为列表中没有 4。这仅适用于两个线程,因为 Thread-1 已经删除了 4。但是如果有三个线程呢?如果不确定 Thread-1 是否已经得到它,那么 Thread-3 怎么会知道不拿 4?我想如果 Thread-3 以 4 开头,它仍然可以工作,但它会做多余的工作。否则必须进行一些非常棘手的同步来避免这种竞争条件。我怀疑这是一个适合并行线程的算法。
  • 即使您通过跨线程共享工作来使其工作,如果您访问相同的结构,无论是数组还是其他结构,它也永远不会很快。多处理的正确方法是将筛子分成合理大小的页面,并为每个页面分配一个线程,使用前台线程合并结果。这就是我在 C#here 中所做的,效果非常好(分段筛的内存访问效率也更高)。该算法可以很容易地转换为 Java,并且运行速度大致相同。

标签: java multithreading algorithm sieve-of-eratosthenes


【解决方案1】:

这个错误比我最初想象的要简单。你所有的线程都在做同样的事情,所以每个线程都做更多的工作。为了使多线程程序运行得更快,您必须划分工作,这必须同时执行。


当您有一个线程访问数据结构时,它可以在一个内核的最快缓存中,使用多个线程并且它们需要协调它们的动作,并且由于大部分工作是更新数据结构,所以很多的时间作为开销丢失。即使您的数据结构不是线程安全的并且可能有损坏的结果,情况也是如此。

顺便说一句,更新 ArrayList 非常昂贵,并且使用集合对象也是一种开销。

使用 BitSet 和一个线程,您将获得更快的结果。

public class BitSetSieveMain {
    private final BitSet set;
    private final int size;

    public BitSetSieveMain(int x) {
        size = x + 1;
        set = new BitSet(size);
        set.flip(2, size);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            long start = System.nanoTime();
            BitSetSieveMain bitSetSieveMain = new BitSetSieveMain(5000);
            bitSetSieveMain.sieve();
            long time = System.nanoTime() - start;
            System.out.println(time / 1000 + " micro-seconds to perform " + bitSetSieveMain);
        }
    }

    public void sieve() {
        int i = 2;
        do {
            for (int j = i*2; j < size; j += i)
                set.clear(j);
            i = set.nextSetBit(i+1);
        } while (i > 0);
    }

    public String toString() {
        return set.toString();
    }
}

终于打印出来了

87 微秒执行 {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73、79、83、89、97、101、103、107、109、113、127、131、137、139、149、151、157、163、167、173、179、181、191、193、197、 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503、509、521、523、541、547、557、563、569、571、577、587、593、599、601、607、613、617、619、631、641、643、647、653、659、 661、673、677、683、691、701、709、719、727、733、739、743、751、757、761、769、773、787、797、809、811、821、823、827、829、 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 116, 1171, 118, 1171, 116, 1171, 118, 1171, 1 187,1193,1201,1213,1217,1223,129,1259,1237,1279,1283,1289,1291,1297,1289,130​​3,1297,1301,1303,1307,1319,1321,1327,1319,1321,1327,1361,1367, 1373,1381,1399,1409,143,1439,1447,143,1453,1459,1451,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549, 1553,1559,1567,1571,1579,1583,1597,1579,1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1699,1693,1697,1699,1709,1721,1723, 1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877,1871,1873,1877,1879,1873,1877,1879,1889,1877,1879,1889,1877,1879,1889,1877,1879,1889,1901,1907,1913,1931, 1933年,1951年,1973,1973,1979,1979,1999,1999,1999,1999,2019,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2087,2089,2099,2111,2113, 2129,2131,2137,2161,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,2273,2281,2269,2273,2281,2287,2293,2297,2309,2311, 2333、2339、2341、2347、2351、2357、2371、2377、2381、2383、2389、2393、2399、2411、2417、2423、2437、 2441,2447,2459,2467,2473,2477,2503,2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2579,2591,2593,2609,2617,2593,2633,2647,2657,2659,2663,2657,2659,2663, 2671,2677,2683,26997,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,2749,2753,2767,2777,2789,2791,2797,2789,2791,2797,2801,2803,2819,2833, 2837,2843,2851,2857,2861,2879,2887,2897,2879,2889,2897,2927,2939,2917,2957,2939,2953,2957,2963,2953,2957,29999,3969,2971,2999,301,3011,3019,3023,3037,3041, 3049,3061,3067,3079,31119,3121,3137,3163,3167,3169,3163,3187,3191,3203,3187,3191,3203,3209,3217,3221,3229,3251,3253,3257,3259, 3271,3299,3301,3307,3313,3319,3323,3329,331,3343,3347,3359,3361,3371,3373,3389,3391,3307,3313,3433,3449,3457,3461,3463,3467, 3469,3491,3499,3529,3517,30039,3541,3533,3557,3559,3547,3557,3559,3571,3581,3583,3593,3607,3631,30013,3623,3631,3637,3643,3659, 3671、3673、3677、3691、3697、3701、3709、3719、3727、3733、3739、3761、3767、3769、3779、3793、379 7, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 4047, 9, 406 398 4007,4013,4019,4021,4027,4049,4051,4057,4073,4079,41111,4127,4129,4111,4127,4153,4157,4159,4153,4157,4159,4177,4201,4159,4177,4201,4111,41177,4201,4211,4177,4201,4211,4117, 4219,2229,4231,4241,4243,4253,4259,4261,4253,4273,4283,4289,4297,4327,433,4339,4327,4357,4363,4349,4391,4397,4373,4391,4397,4409,4421,4423, 4441,4447,4451,4457,4463,4507,4483,4493,4507,4513,4517,4519,4523,4547,4549,4561,4567,4583,4591,4597,4603,4621,4637,4639,4643, 4649,4651,4657,4663,4673,4679,4691,4703,4721,4723,4729,473,4751,4759,4793,4787,4789,4793,4787,4789,4793,4799,489,4793,4799,4801,4813,4817,4831,4861,4817,4831,4861,4871, 4877、4889、4903、4909、4919、4931、4933、4937、4943、4951、4957、4967、4969、4973、4987、4993、4999}

【讨论】:

  • 你的结论越来越模糊! ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-06
  • 1970-01-01
  • 2017-01-05
  • 1970-01-01
相关资源
最近更新 更多