提高嵌套循环的性能

时间:2014-06-17 11:57:37

标签: c# multithreading parallel-processing delegates multiprocessing

我已经为这个例子简化了我的程序,所以我基本上加载了一个文件并将文件中的值添加到列表中。

IList<string> MyList = new List<string>();

Main () 
{
   foreach(Row r in InputFile)
   {
      foreach(Cell c in r)
      {
          AddToList(c.Value);
      }
   }
}

public void AddToTheList(string value)
{
   MyList.Add(value);  
}

我希望加快循环的处理,我不关心添加值的顺序。

我正在考虑并行运行循环和/或将AddToTheList方法视为异步触发而忘记。

使代码使用服务器处理能力并加快处理文件的总时间的最简单方法是什么?

2 个答案:

答案 0 :(得分:4)

更新:如果内部循环足够重以使此任务受CPU限制(而不是IO绑定),那么您可以使用Parallel.ForEach对循环进行分区。这是一个例子:

Parallel.ForEach(InputFile, row =>
{
    foreach(Cell c in row)
        AddToList(c.Value);
});

或者,更改AddToList签名以返回所需的值,然后使用PLINQ。

MyList = InputFile.AsParallel()
                  .SelectMany(row => row.AsParallel()
                                        .Select(cell => TransformCell(cell.Value))
                  .ToList();

public string TransformCell(string value)
{
   return value + " something";
}

使AddToTheList成为一种即发消失的异步方法几乎肯定不是一个好的选择。该方法抛出的异常将无法处理,并且根据您使用的框架,这些可能会使应用程序崩溃。


并行调用AddToTheList并不好 - 这个任务是IO绑定的。 瓶颈在于您从磁盘读取数据的速度有多快。

并行化磁盘访问也不是好事。有两个或多个线程读取同一个文件将不会更快 - 他们无论如何都必须轮流。请参阅Is it possible to use threads to speed up file reading?

的答案
  

使用与文件一样多的线程。

答案 1 :(得分:1)

这取决于。如果解析行和单元格并将值添加到列表中很简单,那么并行执行操作对您没有帮助 - 您将受限于I / O,这比CPU慢很多。

但是,如果解析行需要花费时间,而你实际上没有添加List而是做更复杂的事情,你可以从文件中读取行,然后并行处理行 - 只是为它们预分配内存(List允许你这样做)并且并行访问每一行的List位置。