【问题标题】:Iteration over list and multithreading迭代列表和多线程
【发布时间】:2015-03-22 19:23:27
【问题描述】:

我正在尝试减少循环的执行时间,主要包括读取列表中的数据,对其进行一些计算并将结果写入数组。

我在四核 CPU 上的 20 000 000 个元素列表上尝试这些测试:

  1. 单线程循环
  2. 4 个线程,每个线程中的一个 for 循环迭代列表的 1/4

似乎单线程比 4 个线程快(我也尝试了 2 个)。

我想知道为什么???我认为问题在于 I/O 吞吐量,但我真的很沮丧处理器使用率为 25% 并等待计算。

是否有任何解决方案可以改进/并行化列表上的迭代?

内存是限制因素吗?

编辑:添加代码

public class Main {

public static void main(String[] args) {

    List<Integer> li = new ArrayList<Integer>();
    IntStream.rangeClosed(1, 20_000_000).forEach(i -> li.add(i));

    Integer[] tab = new Integer[1000];
    IntStream.rangeClosed(0, 999).forEach(i -> tab[i] = 0);

    System.out.println("debut");
    Long start = System.currentTimeMillis();

    Thread t1 = new Thread(new ThreadRunner(li, tab, 1, 0));
    Thread t2 = new Thread(new ThreadRunner(li, tab, 4, 1));
    Thread t3 = new Thread(new ThreadRunner(li, tab, 4, 2));
    Thread t4 = new Thread(new ThreadRunner(li, tab, 4, 3));

    t1.start();
    t2.start();
    t3.start();
    t4.start();
    try {
        t1.join();
        t2.join();
        t3.join();
        t4.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("time : " + (System.currentTimeMillis() - start) + "ms");

}

}

public class ThreadRunner implements Runnable {

List<Integer> l;
private int inc;
private int start;
private Integer[] tab;

public ThreadRunner(List<Integer> l, Integer[] tab, int inc, int start) {
    this.l = l;
    this.inc = inc;
    this.start = start;
    this.tab = tab;
}

@Override
public void run() {
    int fake = 0;
    for(int i = start; i<l.size(); i+=inc){

        fake = l.get(i);

    }

    System.out.println("fake : " + fake);

}

}

【问题讨论】:

  • 请分享代码。
  • 完全依赖于代码和算法。首先,该问题必须具有可并行性。然后,必须编写并行代码以利用这一点。
  • 你说得对,我会尽快发布。但它是对列表进行循环并将 1 添加到数组元素(选择列表索引模 1000 的元素)我运行 4 个线程并等待 join() 的极简主义。每个循环在列表中进一步推进 4 个元素
  • 不要浪费时间把代码用英文写出来,魔鬼在细节中,细节在代码中。
  • 是的,你的权利,当我发布问题时,我不在正确的电脑上,对不起

标签: java multithreading loops


【解决方案1】:

启动线程然后等待它们完成需要一些时间。我怀疑时间比迭代列表中的几百万个元素所花费的时间要长得多。

是什么让您相信这是代码中最重要的优化部分,并且生成线程会加快它的速度?

记住优化规则:http://en.wikipedia.org/wiki/Program_optimization#When_to_optimize

注意:您测量执行时间的方式可能会误导您。编写微基准测试非常棘手。

【讨论】:

  • 是的,我明白了。但是在真正的代码中,我在 for 循环中有更多的计算,并且对于单线程或 4 线程,我有 2 秒的执行时间,我认为线程管理开销不会花费那个时间。我真的认为记忆力是限制因素,我想要你的意见
  • 您是否测量了时间花费在哪里(可能使用分析器)?另外,在编写基准之前阅读code.google.com/p/caliper/wiki/JavaMicrobenchmarks
【解决方案2】:

Java 无法决定它使用哪个内核。您的操作系统将做出该决定。所以你的 4 个线程确实在一个内核上运行。

【讨论】:

  • 我们不确定。直到添加代码。
  • 是的,这是一个很好的观点,我没有想到,但我运行了很多测试,我看到处理器负载因添加线程而增加了 25%
猜你喜欢
  • 2012-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-11
  • 2014-10-23
  • 2016-05-15
  • 2019-05-05
  • 2012-05-12
相关资源
最近更新 更多