如何在ASP.NET中并行化CPU密集型操作

本文关键字:并行化 CPU 密集型 操作 NET ASP | 更新日期: 2023-09-27 17:53:02

. NET MVC应用程序,我有一个项目与活动图跟踪。

一个项目不是只有一个根,而是有多个根。每棵树都可能是复杂而深入的,每个节点都依赖于其他节点,比如日期和细粒度的用户权限。

每次对一个节点进行操作时,我都需要处理所有的项目图因为即使是不同的分支也要相互依赖。

结构平面存储在SqlServer数据库中。

为了创建树,我有一个递归函数,它做了很多事情来为每个节点创建一些数据(在当前用户的上下文中)。

例如,我有一个有3000个节点的项目,用一个创建整个图的调用来处理需要超过2秒。

public static List<Nodes> GetProject(...) {
  var list = new List<Nodes>;
  CreateTreeRecursive(...);
  return list;
}

记住我有多个根。这让我可以并行化工作并独立处理每个分支。

如果我并行执行Task。运行或并行。每次创建整个图形的时间在15到50毫秒之间,快了50倍。

public static List<Nodes> GetProject2(...) {
  var list = new List<Nodes>;
  Parallel.ForEach(...,
    (root) => {
      ...
    });
  return list;
}

坏消息是你不应该在ASP.NET中创建线程。

在特定的情况下,我没有很多并发用户,但是有大约200个用户你不可能真的知道。

另一件事是,一个项目的根可以有很多,最多100个,所以很多线程会被创建。

这个解决方案很简单,但并不适用。

是否有一些方法可以以简单的方式做到这一点,或者我唯一的选择是将工作卸载给一些可以跨多个线程并异步等待的外部服务?

如果是这样的话,我希望你能给我一些建议。

需要明确的是,这是针对项目上的任何用户交互所做的操作。我不能缓存结果,太不稳定了。我不能在某处排队,最终得到结果。

谢谢

如何在ASP.NET中并行化CPU密集型操作

坏消息是你不应该在ASP.NET中创建线程。

这不是真的,这个错误的假设阻碍了正确的解决方案。

可以创建线程。您可能想到的风险是,您可能耗尽线程池的容量。这通常是不容易做到的。

你的线程是CPU限制的。这意味着在池耗尽之前,您的服务器就已经完全超载了。池容量不是限制因素。

通过一些假设,我们可以构建一个具体的场景:一个8核服务器饱和为8个线程(可以像这里一样运行)。但是,如果线程少于100个,则不会认为线程池过载。(实际数字有所不同。100在很多情况下都应该是安全的

进一步,Parallel.ForEach使用池线程。它不会创建有意义的线程数量。它也不会为每个输入项占用一个线程。

我不觉得有什么好担心的。