繁体   English   中英

如何在 C# 中高效地并行运行代码?

[英]How to efficiently run code in parallel in C#?

我认为我的问题如下——如何为并行执行做准备?

我当前的代码类似于这种模式:

  var worker = new Worker();
  while (true)
    worker.RandomTest();

RandomTest主要受 CPU 限制。 在极少数情况下,worker 会写入文件(在获得对文件的锁定之后),但这种情况很少见,因此不需要考虑 I/O 延迟。

我想并行运行它,我可以使用Parallel.For并使用一些大数字作为上限(而不是while ),但我有问题如何准备这样的执行,因为我不想创建工人每次迭代。

为了做好准备,我需要提前知道并行池的大小,并且还需要知道线程/任务/作业的索引在内部循环,这样我才能知道如何将当前执行路径与工作线程相关联。


事实证明,我的问题更为根本。 我不知道如何做准备,所以既然我有无限循环,我想为什么不呢:

  Parallel.Loop(0,1000,(i,_) => {
    var worker = new Worker();
    while (true)
      worker.RandomTest();
  }

到目前为止,我认为启动的执行与可用的 CPU 内核相比将处于合理的范围内。 但是没有——Parallel 疯狂地创建新的迭代,所以已经创建的工作基本上因为新工作的涌入而停滞不前。

当然,我可以对要运行的并行作业的固定数量进行硬编码,但是计算出多少不能太多也不能太少的责任在我身上。

我知道怎么放固定号,但是怎么放好号呢? 即当我在不同的机器上或在不同的条件下运行程序时(例如在后台使用 CPU 要求很高的进程)?

这里的Worker不是线程安全类型,因此我创建了与要执行的工作一样多的 worker。

解决这个问题的一种方法是启动与内核数量相等的线程, while在每个线程中进行无限循环:

for (int i = 0; i < Environment.ProcessorCount; i++)
{
    _ = new Thread(() =>
    {
        Worker worker = new();
        while (true) worker.RandomTest();
    });
}

这些线程是前台线程,因此即使在退出Main方法后它们也会使程序保持活动状态。 如果任何循环失败,整个程序将立即崩溃并出现未处理的异常。 这种原始行为可能更接近您想要做的事情,而不是复杂的Parallel类及其晦涩的分区程序。

关于最佳并行度,对于受 CPU 限制的工作负载,通常是Environment.ProcessorCount 使用此配置,并行执行将使用您机器的所有核心,而无需太多线程切换。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM