为什么这个Parallel.ForEach循环不能提高性能?

时间:2011-11-10 07:00:44

标签: c# .net multithreading

我有以下代码:

           if (!this.writeDataStore.Exists(mat))
            {
                BlockingCollection<ImageFile> imageFiles = new BlockingCollection<ImageFile>();
                Parallel.ForEach(fileGrouping, fi => DecompressAndReadGzFile(fi, imageFiles));


                this.PushIntoDb(mat, imageFiles.ToList());
            }

DecompressAndReadGzFile是包含此方法的同一类中的静态方法。根据方法名称,我正在解压缩并读取gz文件,其中很多,即最多1000个,因此并行化的开销这是有益的。但是,我没有看到好处。当我使用ANTS性能分析器时,我发现它们运行的​​时间与完全没有并行化的时间完全相同。我还使用进程资源管理器检查CPU内核,看起来可能在两个内核上完成了工作,但是一个内核似乎正在完成大部分工作。至于让Parallel.ForEach并行解压缩和读取文件,我不理解什么?

更新的问题:从文件列表中读取信息的最快方法是什么?

问题(简​​化):

  1. 有一大堆.gz文件(1200)。
  2. 每个文件都有一行包含“DATA:”,位置和行号不是静态的,可能因文件而异。
  3. 我们需要在“DATA:”之后检索第一个数字(仅为了简单起见)并将其存储在内存中的对象中(例如List)
  4. 在最初的问题中,我使用的是Parallel.ForEach循环,但我似乎没有超过1核心的CPU绑定。

2 个答案:

答案 0 :(得分:12)

线程是否可能花费大部分时间等待IO?通过一次读取多个文件,您可能会使磁盘捶打多于单个操作。您可以通过顺序使用单个线程读取来提高性能,但随后将CPU绑定解压缩到单独的线程......但实际上您可能发现只需要一个线程执行解压缩,如果磁盘比减压过程本身慢。

测试这种方法的一种方法是首先将需要解压缩的文件复制到ramdisk上,然后仍然使用当前代码。我怀疑你会发现你受CPU限制,所有的处理器几乎都在忙着。

(你还应该考虑你正在对解压缩的文件做些什么。你是否正在将它们写回磁盘?如果是这样的话,那么你可能还在等待一个颠簸的磁盘。)

答案 1 :(得分:0)

您的静态方法是否有可能在其调用之间共享任何全局资源。 因为在这种情况下,这个静态方法将被顺序调用,并没有平行的好处。 你能把你的fileGrouping类代码?