【发布时间】:2014-01-27 05:56:49
【问题描述】:
我正在尝试改进我正在执行的某些数据处理的运行时间。数据以各种集合开始(主要是Dictionary,但还有一些其他IEnumerable 类型),处理的最终结果应该是Dictionary<DataType, List<DataPoint>>。
我的所有这些工作都很好......除了它需要将近一个小时才能运行,而且它需要在 20 分钟内运行。没有任何数据与同一集合中的任何其他数据有任何联系,尽管它们经常交叉引用其他集合,所以我想我应该并行化它。
处理的主要结构有两级循环,中间有一些处理:
// Custom class, 0.01%
var primaryData= GETPRIMARY().ToDictionary(x => x.ID, x => x);
// Custom class, 11.30%
var data1 = GETDATAONE().GroupBy(x => x.Category)
.ToDictionary(x => x.Key, x => x);
// DataRows, 8.19%
var data2 = GETDATATWO().GroupBy(x => x.Type)
.ToDictionary(x => x.Key, x => x.OrderBy(y => y.ID));
foreach (var key in listOfKeys)
{
// 0.01%
var subData1 = data1[key].ToDictionary(x => x.ID, x => x);
// 1.99%
var subData2 = data2.GroupBy(x => x.ID)
.Where(x => primaryData.ContainsKey(x.Type))
.ToDictionary(x => x.Key, x => ProcessDataTwo(x, primaryData[x.Key]));
// 0.70%
var grouped = primaryData.Select(x => new { ID = x.Key,
Data1 = subData1[x.Key],
Data2 = subData2[x.Key] }).ToList();
foreach (var item in grouped)
{
// 62.12%
item.Data1.Results = new Results(item.ID, item.Data2);
// 12.37%
item.Data1.Status = new Status(item.ID, item.Data2);
}
results.Add(key, grouped);
}
return results;
listOfKeys 很小,但每个grouped 将有几千个项目。 我应该如何构建这个结构,以便对item.Data1.Process(item.Data2) 的每个调用都可以排队并并行执行?
根据我的分析器,所有ToDictionary() 调用一起占用大约 21% 的时间,ToList() 占用 0.7%,内部 foreach 内的两个项目一起占用 74%。因此,我将优化重点放在了那里。
我不知道我是否应该使用Parallel.ForEach() 来替换外部foreach,内部一个,两者,或者是否应该使用其他一些结构。我也不确定我是否可以对数据(或保存它的结构)做些什么来改进对它的并行访问。
(请注意,我被困在 .NET4 上,所以无法访问 async 或 await)
【问题讨论】:
-
另外,如果您正准备进行并行编程,我建议您阅读 Microsoft 提供的免费电子书“Patterns of Parallel Programming”,它详细介绍了常见的陷阱,例如做得太小或工作单元太大(第 26-28 页)。
-
@ScottChamberlain - 我已经运行了一个分析器,到目前为止,最大的块是
item.Data1.Process()。在那里,我几乎没有什么可以优化的——我已经修剪/缓存了我能做的。在实际代码中,内部foreach内部实际上有两个步骤,它们总共占用了运行时间的 74%。 -
话虽如此,我不知道它被调用了多少次,所以高数字至少部分是调用它的绝对数量的函数。我也一定会读一读这本电子书。谢谢!
-
嗯,看来 Parallel.foreach 在外循环上必须值得一试。
-
@TonyHopkinson - 在我写这个问题时,它实际上一直在运行。但到目前为止已经 25 分钟,这实际上比单线程代码花费的时间长,所以我质疑这个结果。我将重新运行测试并添加结果。
标签: c# c#-4.0 parallel-processing task-parallel-library