【发布时间】:2012-04-18 14:16:40
【问题描述】:
我目前正在编写一个批量处理算法,用于检测从磁盘流式传输的音频中的音高。我已经收紧了我的算法,使其几乎可以实时运行串行流数据。
理想情况下,我希望系统的工作速度比实时速度快,这样我就可以将实时数据交给它,并在不长的延迟后生成音高轨迹数据。
现在让我印象深刻的是数据的串行处理是我可以提供大量加速的地方。我在四核 i7(有 8 个硬件线程)上运行,所以我应该能够通过跨多个块分散处理来显着提高速度。
目前,我正在执行以下操作:
- 从磁盘流式传输数据
- 缓冲数据,直到获得我希望分析的窗口大小。
- 处理数据窗口。
- 将数据复制回 n 个样本(其中 n 是我想要滑动的量(在 80 毫秒的窗口中,这可以低至 1 毫秒!)
- 冲洗并重复。
现在让我震惊的是,一旦我有了一个窗口,我就可以轻松地将数据复制到给定的线程工作缓冲区中(以及提供将写入结果的内存位置)。这样,我可以有效地缓冲多达 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