【问题标题】:Would adding more threads increase the performance of my program [closed]添加更多线程会提高我的程序的性能[关闭]
【发布时间】:2012-01-05 02:32:52
【问题描述】:

在我的程序中,我有一个 while 循环,它遍历一组图片的数组列表,并对它们进行一系列处理以更改它们的外观和图像类型,然后将它们写入磁盘。我的问题是添加多个线程来处理图像或保存图像会加快速度,如果是这样,最好的方法是什么。 ArrayList images = new ArrayList();//超过500张图片 ArrayList 路径 = 新的 ArrayList (); int len = images.size();

for (int i =0; i < len ; i ++)
{
BufferedImage image  = process (images.get(i))//takes about a second 
ImageIO.write(image, "jpg", new File(getImagePaths().get(i)));


}

【问题讨论】:

  • 您尝试改进的代码示例将增加社区提供帮助的几率。 :) 根据您的描述,它可能是磁盘 I/O,在这种情况下,多线程可能无济于事。您是否尝试过分析您的应用以确定性能瓶颈在哪里?
  • 假设您的进程受 CPU 限制,我会使用 Executors.newFixedThreadPool,它的线程数与您拥有的核心 Runtime.availableProcessors()execute() 的线程数相同,每个都作为循环内的任务写入。
  • @GregHewgill 如果我们一直远离它们,那么我们如何学习它们..

标签: java multithreading performance


【解决方案1】:

您可以将您的列表划分为 n 个块,以便您拥有大小为 list / n 的块,然后您可以让 n 个线程对这些图像“块”进行操作。这样您就可以同时完成更多的工作。

为了解决一些提出的问题,它很可能也会增加 I/O 并发性,因为在单线程运行中,它会在第一次未命中和阻塞时出错,然后再次出错以读取第二张图像,等等......在多线程方式中,它将一次阻塞 n 个图像,这允许 I/O 调度程序一次处理更多 I/O(这通常是一件好事)。这意味着即使在单核处理器中也可以提高性能,因为 I/O 重叠,并且在 I/O 阻塞线程等待时,更多线程可以在核心上运行。

【讨论】:

  • 当然,考虑到有足够的内存,或者问题不在于磁盘 I/O,或者它不是单核机器,或者其他任何数量的东西都会导致效率低下。 OP的问题实在是太宽泛了,缺乏有用的信息,而且他对线程的理解显然是有限的。
  • @BrianRoach 你说得对,我假设了很多事情。磁盘 I/O 可能是一个问题,但多线程会有所帮助,因为它会导致更多的并发 I/O 而不是 I/O 未命中,然后是阻塞调用,并且对每个图像重复,在这种情况下,即使在单核机器上也会如此帮助。
【解决方案2】:

是的,很可能是因为:

1) 您的计算机可能有 2 到 4 个 CPU 或内核

2) 图像处理通常是 CPU 密集型的

3) 因此,大的 CPU 负载可以被拆分为多个同时运行的任务。

这会一直有效吗?

没有。如果您的进程是 i/o(互联网、磁盘或内存)受限的(例如,每个图像需要 2G 内存,或者必须写入大量临时文件),您将不会看到线性加速 - 因为CPU 速度的提升将被执行 i/o 的时间所抵消,这将减慢您的程序,无论您必须有多少个处理器来分担图像处理的负载。 就像做面条一样 - 煮面条需要 10 分钟。即使你同时有 8 个不同的燃烧器 - 面条吸收水分仍然需要 10 分钟,所以平行化也无济于事。

伪代码:

   //just a reminder ! 
   public static final int MAX_SEM=8;
   processAll()
   {
     //create a new semaphore with 4 slots.
     semaphore = new Semaphore(MAX_SEM) ;
     while(! images.empty())
         if(semaphore has a slot) 
           Image img=images.pop();
           sempahore.decrement()
           Thread().run( new Runable() { public void run() {process(img);} } 
         else
           Thread.sleep(1000);
    }

    process(Image i)
    {   do some work  on i 
        semaphore.increment()
    }

【讨论】:

  • 如果我说添加了 40 个不同的线程怎么办?
  • 如果你有 40 个内核/处理器,那就去做吧。只要确保第一个的优先级高于最后一个,这样您的硬盘就不会整天工作,也没有线程得到他们想要的。
  • k 刚刚尝试过类似的方法,但似乎我无法真正为 evrey single iamge 创建线程,否则它会变得超级滞后,我想我会尝试最多 4 次
  • 不要在必要时创建更多线程 --- 如果你这样做,结果将是不可预测的。特别是如果这些是内存密集型的。从 2 开始 - 如果性能翻倍,请转到 4,然后尝试 8。除非您知道您的 CPU、内存限制和一般线程,否则我不会超过 8。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-18
  • 1970-01-01
相关资源
最近更新 更多