【发布时间】:2012-11-14 16:55:56
【问题描述】:
我想并行处理逐帧处理多个视频剪辑的应用程序。每个剪辑的每一帧的序列很重要(显然)。 我决定使用 TPL 数据流,因为我相信这是数据流的一个很好的例子(电影帧就是数据)。
所以我有一个从数据库加载帧的进程(可以说是一批 500 个,全部聚集在一起)
Example sequence:
|mid:1 fr:1|mid:1 fr:2|mid:2 fr:1|mid:3 fr:1|mid:1 fr:3|mid:2 fr:2|mid:2 fr:3|mid:1 fr:4|
并将它们发布到 BufferBlock。对于这个 BufferBlock,我将 ActionBlocks 与过滤器链接起来,让每个 MovieID 有一个 ActionBlock,这样我就可以获得某种数据分区。每个 ActionBlock 都是顺序的,但理想情况下,多部电影的多个 ActionBlock 可以并行运行。
我确实有上述网络工作并且它确实并行运行,但根据我的计算,只有八到十个动作块同时执行。我计时了每个 ActionBlock 的运行时间,大约为 100-200 毫秒。 我可以采取哪些步骤来至少双倍并发?
我确实尝试将操作委托转换为异步方法,并在 ActionBlock 操作委托中使数据库访问异步,但没有帮助。
编辑:我实现了额外级别的数据分区:具有奇数 ID 的电影的帧在 ServerA 上处理,偶数电影的帧在 ServerB 上处理。应用程序的两个实例都访问了同一个数据库。如果我的问题是 DB IO,那么我不会看到处理的总帧数有任何改善(或者很少,低于 20%)。但我确实看到它翻了一番。所以这让我得出结论,Threadpool 并没有产生更多线程来并行处理更多帧(两台服务器都是四核的,分析器显示每个应用程序大约有 25-30 个线程)。
【问题讨论】:
-
您的操作块是否将任何数据写入磁盘或返回 SQL?你的动作块有任何 IO 吗?这可以通过从 SQL 获取数据来限制。当您说 CPU 低于 50% 是平均值或保持低于 50% 时。
-
ActionBlock 从/向 SQL 读取/写入数据。 CPU 确实保持在 50% 以下,平均为 25%。我确实将数据库访问方法转换为异步,它的生产力提高了大约 20%。但仍然认为我可以做得更好。
-
Parallel Stacks 确实显示了大约 18-20 个线程池线程。如果我能把这个提高到 50,我会是一个快乐的露营者。
-
“我可以采取哪些步骤来至少双倍并发?”恕我直言,你不能只说“我想加倍 X”,这意味着它可以完成。是否可能取决于您在此处列出的更多因素。充其量,我们可以为您提供有关如何改进并发性或整体处理的指导。
标签: c# .net task-parallel-library async-await tpl-dataflow