【问题标题】:Limiting work in progress of parallel operations of a streamed resource限制流式资源的并行操作正在进行的工作
【发布时间】:2012-06-22 15:27:23
【问题描述】:

我最近发现自己使用SemaphoreSlim 类来限制对(大型)流式资源的可并行化操作的进行中的工作:

// The below code is an example of the structure of the code, there are some 
// omissions around handling of tasks that do not run to completion that should be in production code

SemaphoreSlim semaphore = new SemaphoreSlim(Environment.ProcessorCount * someMagicNumber);
foreach (var result in StreamResults()) 
{
  semaphore.Wait();
  var task = DoWorkAsync(result).ContinueWith(t => semaphore.Release());
  ...
}

这是为了避免将太多结果带入内存而导致程序无法处理(通常通过 OutOfMemoryException 证明)。尽管代码有效并且性能合理,但仍然感觉很笨拙。值得注意的是,someMagicNumber 乘数虽然通过分析进行了调整,但可能没有达到应有的最佳效果,并且对DoWorkAsync 的实现变化没有弹性。

就像线程池可以克服调度许多事情执行的障碍一样,我想要一些可以克服基于可用资源调度许多事情加载到内存中的障碍的东西。

由于确定是否会发生 OutOfMemoryException 是不可能的,我很感激我正在寻找的东西可能只能通过统计手段实现,甚至根本无法实现,但我希望我遗漏了一些东西。

【问题讨论】:

  • 你介意DoWorkAsync()实际上是同步执行的吗?你可以使用 C# 5 吗?这与yield return 有什么关系?
  • @svick 我宁愿 DoWorkAsync 没有同步执行,因为执行了网络 IO 并且可以使用完成端口线程。 yield-return 被标记只是因为它是来自StreamResults 的结果的返回方式。我不能使用 .C#5(或 4.5,或 MS 现在调用的任何版本!),只能使用 C#4.0
  • 它被称为C# 5.0,它将与.Net 4.5一起发布。是的,.Net 版本号可能会让人感到困惑。
  • 如果它在做网络 IO,那么找到正确的并行度几乎取决于你。 ThreadPool(或 TPL 中的任何内容)无法真正为您做到这一点。

标签: c#-4.0 concurrency task-parallel-library yield-return


【解决方案1】:

在这里我想说你可能想多了这个问题。超调的后果是相当高的(程序崩溃)。太低的后果是程序可能变慢。只要您仍有超出最小值的缓冲区,进一步增加缓冲区通常几乎没有影响,除非管道中该任务的处理时间非常不稳定。

如果您的缓冲区不断被填满,则通常意味着管道中它之前的任务比它后面的任务执行得快很多,因此即使没有一个相当小的缓冲区,它也可能始终确保它后面的任务有一些工作。获得缓冲区 90% 的好处所需的缓冲区大小通常会非常小(可能有几十个项目),而需要获得 OOM 错误的一方就像 6+ 巨头的订单 更高。只要您介于这两个数字之间(这是一个相当大的范围),您就可以了。

只需运行您的静态测试,选择一个静态数字,可能会为“以防万一”增加几个百分点,您应该会很好。最多,我会将一些幻数移动到配置文件中,以便在输入数据或机器规格发生根本变化时无需重新编译即可更改它们。

【讨论】:

  • 我认为问题不在于缓冲区的大小,而在于并行执行。
  • @svick 两者都有。有许多相关的操作,并行运行,创建管道。当一个任务完成一个工作单元时,它将结果传递给下一个任务,下一个任务对其执行另一个工作单元,并将其传递给管道中的下一个操作员。所有这些任务都在同时进行。每个任务之间都有一个缓冲区,这样它们就不需要等待下一个任务收到结果才能开始下一个工作单元;如果所有任务的工作时间不完全相同,这将减少等待时间。
  • 我不确定你在说什么,但我很确定这不是有问题的代码。那没有任何管道或类似的东西。
猜你喜欢
  • 1970-01-01
  • 2019-05-07
  • 2017-09-14
  • 2023-02-10
  • 1970-01-01
  • 2022-12-11
  • 2017-11-02
  • 1970-01-01
  • 2022-01-01
相关资源
最近更新 更多