【发布时间】:2016-09-26 09:15:06
【问题描述】:
我有以下问题:
我正在对相当 CPU 密集型工作负载使用 parallel.foreach 迭代(对多个项目应用一种方法)并且它对大约前 80% 的项目运行良好 - 使用所有 cpu 内核非常好。
随着迭代似乎接近尾声(我会说大约 80%),我看到线程数开始逐个内核下降,最后大约 5% 的项目被处理只有两个核心。因此,要使用所有内核直到结束,它在迭代结束时会非常缓慢地减速。
请注意,每个项目的工作量可能会有很大差异。一项可以持续 1-2 秒,另一项可能需要 2-3 分钟才能完成。
任何想法,建议都非常欢迎。
使用的代码:
var source = myList.ToArray();
var rangePartitioner = Partitioner.Create(0, source.Lenght);
using (SqlConnection connection =new SqlConnection(cnStr))
{
connection.Open();
try
(
Parallel.ForEach(rangePartitioner, (range, loopState) =>
{
for(int i = range.Item1; i<range.Item2; i++)
{
CPUIntensiveMethod(source[i]);
}
});
}
catch(AggretateException ae)
{ //Exception cachting}
}
【问题讨论】:
-
你想用这段代码做什么?您是否试图通过 single 连接“并行”执行 SQL 语句?为什么您认为“并行执行”有助于解决 SQL 性能问题?
-
@LasseV.Karlsen 注意 SqlConnection。我怀疑 OP 正试图通过暴力破解 sql 命令来解决 sql 性能问题,这当然会导致相反的结果,因为阻塞
-
这看起来像the XY Problem 的情况。 OP 存在 SQL 性能问题,并假设可以通过并行执行命令来修复它。当失败时,OP 会询问
Parallel.ForEach而不是 actual 问题,应该回答这个问题,例如使用 SqlBulkCopy、TVP、重写低效的 SQL 语句或将多个命令批处理为一个 -
@Horia 你误会了。每个单独的命令都需要一些时间才能到达服务器并返回。单个批处理命令虽然避免了过多的往返。在任何情况下,在 ETL 场景中,您都在处理 流 数据。这意味着您需要例如管道中的一些工作人员以 CPU 的最大值处理数据。这就是 SSIS 所做的。这也是 TPL 数据流的作用。
Parallel.ForEach虽然只是将输入拆分为可能不平衡的 X 分区。如果其中一个分区干涸,相关任务将闲置。 -
不要使用分区,因为每次迭代的工作量都很大。
标签: c# performance parallel.foreach