提高嵌套循环的性能

本文关键字:性能 嵌套循环 | 更新日期: 2023-09-27 18:09:02

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

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方法视为异步触发并忘记。

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

提高嵌套循环的性能

Update:如果内部循环足够重,使该任务受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绑定的。瓶颈在于从磁盘读取数据的速度有多快。

并行磁盘访问也不好。让两个或多个线程读取同一个文件并不会更快——它们必须轮流读取。看看这个问题的答案:是否有可能使用线程来加速文件读取?

使用尽可能多的线程。

看情况。如果解析行和单元格并向列表中添加值很简单,那么并行处理将无法帮助您-您将受到限制I/O,这比CPU慢得多。

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