使用C#.NET在一个方法中正确地并行处理许多小任务



我正在使用.NET Framework 4.72在C#中实现图像处理算法,需要减少计算代码。总的来说,代码是顺序的,但有相当多的方法的参数彼此不依赖。例如,它可能类似于这个

public void Algorithm(Object x, Object y) {    
x = Filter(x);
x = Morphology(x);
y = Filter(y);
y = Morphology(y);
var z = Add(x,y);
//Similar pattern of separate operation that are then combined.
}

这些功能通常需要大约100ms到500ms。它们可以并行,我的方法是这样的:

public void Algorithm(Object x, Object y) {  
var xTask = Task.Run(() => {
x = Filter(x);
x = Morphology(x);
});
var yTask = Task.Run(() => {
y = Filter(y);
y = Morphology(y);
});
Task.WaitAll(xTask, yTask);
var z = Add(x,y);
}

这似乎是可行的,类似的代码运行速度大约是原来的两倍。(注意,整件事都被封装在最顶层函数中的另一个Task.Run中,所以这就是为什么我在这里不是await

问题:这是一种有效的方法,还是有另一种更安全或有效的方法来并行处理许多小方法调用?

更新:这不是用于并行处理一批图像。它是关于尽可能快地处理单个图像。

这是足够有效的-如果您可以并行处理您的工作负载,那么您应该这样做。您只需要非常清楚您的工作负载何时可以并且应该并行,以及何时需要按顺序执行。

您还需要考虑创建新任务的成本与这样做的好处(即有时避免非常小、非常快的任务(。

我强烈建议您创建额外的方法和集合来管理任务——当它们完成时,并处理并行运行的许多单独的集合。避免锁定、管理共享内存/变量等。例如,您是否一次只处理一个映像,或者如果有可用的核心,您是否可以开始处理下一个映像?

使用Task.WaitAll((时需要非常小心——显然,您需要在某个时刻将所有工作绘制在一起,但要小心不要锁定或阻止其他工作。

有很多关于你可以使用的各种模式的文章(这里的管道听起来很匹配(。

以下是一些入门产品:

https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/tpl-and-traditional-async-programming

https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/potential-pitfalls-in-data-and-task-parallelism

最新更新