【问题标题】:Taskpool system for .NET.NET 的任务池系统
【发布时间】:2012-04-18 14:16:40
【问题描述】:

我目前正在编写一个批量处理算法,用于检测从磁盘流式传输的音频中的音高。我已经收紧了我的算法,使其几乎可以实时运行串行流数据。

理想情况下,我希望系统的工作速度比实时速度快,这样我就可以将实时数据交给它,并在不长的延迟后生成音高轨迹数据。

现在让我印象深刻的是数据的串行处理是我可以提供大量加速的地方。我在四核 i7(有 8 个硬件线程)上运行,所以我应该能够通过跨多个块分散处理来显着提高速度。

目前,我正在执行以下操作:

  1. 从磁盘流式传输数据
  2. 缓冲数据,直到获得我希望分析的窗口大小。
  3. 处理数据窗口。
  4. 将数据复制回 n 个样本(其中 n 是我想要滑动的量(在 80 毫秒的窗口中,这可以低至 1 毫秒!)
  5. 冲洗并重复。

现在让我震惊的是,一旦我有了一个窗口,我就可以轻松地将数据复制到给定的线程工作缓冲区中(以及提供将写入结果的内存位置)。这样,我可以有效地缓冲多达 7 个(让线程 8 保持打开以泵送数据)线程池将处理的数据线程。

当我尝试提交第 8 个音频窗口时,我希望池阻塞,直到有线程可用于处理数据等等。我的想法是让 7 个线程不断地处理数据。根据以前的经验,我希望这样做可以提高大约 5 倍的速度。

过去我在 C++ 下编写了我自己的基于任务的系统,该系统可以完美地完成这项工作,但这个应用程序是在 C# 下开发的。为了在 C++ 下以低开销获得良好的并行性,我花费了大量时间来构建良好的无锁队列机制。

我宁愿希望在 C# 下,有人会为我做这件事而感到痛苦。但是我找不到任何似乎可行的东西。我查看了 System.Threading.ThreadPool ,它似乎无法检查当前有多少线程在运行。更不用说开销似乎令人望而却步。然后出现了一个大问题,即我无法重新使用现有的预分配结构(这在我的处理中很重要),这迫使我每次提交工作项时都重新创建它。这有一个巨大的缺点,就是我生成工作的速度比我处理它的速度要快,所以我最终不仅浪费了大量时间来设置我真的不需要的结构和工作空间,而且我的内存使用量也失控了。

然后我发现了 System.Threading.Tasks,但它似乎也没有提供我想要的功能。

我想我可以通过互操作使用我的 C++ 任务管理器,但我真的认为在这个时代已经有人设置了类似的东西。所以我错过了什么吗?或者谁能​​给我一个这样的任务管理引擎的链接?

【问题讨论】:

  • 我不确定我是否遵循。为什么在创建“工作项”时需要复制结构?为什么不只传递对它的引用(即 - 将它放在一个类中并传递实例)?
  • 我认为没有什么比简单的单一生产者/多消费者算法更需要的了。
  • @zmbq:问题是我需要一组大型便签本区域来进行处理。这些暂存器必须预先设置,因为它们设置起来并不那么快。我对我的 C++ 系统所做的是预先设置 8 个这样的结构,然后在当前准备好处理的任何数据上重新使用它们。另一个问题是这些便签本非常大,所以我不能随意创建 50 个(例如,50 个需要大约 0.5GB 的内存)。
  • @Hans Passant:这正是我想要的......我真的不想自己实现它。我在寻找一种机制时遇到了严重的问题,我可以简单地阻止生产者线程,直到消费者可用......

标签: c# .net threadpool task


【解决方案1】:

我会在这里使用 Task Parallel 数据流库。它旨在允许创建可以链接在一起的进程块,并显式控制并行度和阻塞语义。

【讨论】:

    【解决方案2】:

    好吧,在这些情况下,我建议使用 ZeroMQ 。它可以让你很容易地控制消费者的数量。

    至于您的便签本区域,首先,0.5GB 在当今时代并不是很多内存。我认为我的手机有更多的内存,更不用说我的桌面了......如果你想真正轻松地减少内存消耗,只需为每个线程创建一个暂存区,将它们全部放在一个池中并让生产者获得在排队任务之前的便签本区域,附加任务的该区域。当消费者完成后,将便签本区域返回到池中。

    【讨论】:

    • 我不知道你的情况,但是当我只需要大约 80 meg 时,半场演出似乎是一种可怕的内存浪费......唉,我希望更多的程序员像我一样思考:(
    • 这不是浪费内存——它会在你的程序完成后出现......严重的是,除非它是一个真正的问题,否则优化你的内存占用是没有意义的。这是一个真正的问题吗?
    • 是的……很明显……浪费任何资源都是不好的……但是不要争论为什么毫无意义的过度使用内存是一件坏事。
    • 这是内存/时间的权衡。在这种情况下,您使用的内存越多,您花在编码和调试上的时间就越少。从那时起,这取决于您自己的优先事项。
    • 但不是吗?我不需要排队 50 个项目?它对我的处理时间没有帮助,也对我的内存使用没有帮助?权衡在哪里?
    【解决方案3】:

    Task Parallel Library 专为您要解决的任务而设计和实施!您也可以通过管道处理此过程。

    所以你必须确保:

    【讨论】:

    • 我宁愿希望 TPL 能做我想做的事.. 但到目前为止我还没有搞清楚它的运气......例如我如何要求一个项目排队但是阻塞队列直到线程可用?
    • @Goz - 在 BlockingCollecition 链接下。
    • @HenkHolterman:你能不能给我举个例子?
    • Pipelines 链接下有一个示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多