【发布时间】:2016-11-18 10:29:33
【问题描述】:
对于那些希望并行化计算密集型算法的人,让我为您指出这份关于利用 .NET 4 及更高版本的任务并行库的常见模式的文档:https://www.microsoft.com/en-us/download/details.aspx?id=19222
但是,有一种我认为相当普遍的模式,我有它没有包含在那个其他很棒的文档中......
我说 DataTable 中有 100 行在 N 列中有一组输入,我需要为此计算 M 列中的一些输出。每一行都可以独立计算,所以它似乎是并行化的首要条件。
但是,要进行该计算,我需要首先构建一个海量数据结构。一旦为一行构建,我可以简单地重置它以将其用于另一行。所以,我不想为每一行从头开始重建它……这比重置要长得多。但是并行计算不能共享该数据结构,因为它们都将对其进行修改……相反,它们都需要自己的。
太棒了,从算法上讲,我需要为我可用的每个处理器内核启动一个线程,首先构建自己的海量数据结构。然后它应该计算一行,重置,计算另一行,重置,等等,直到没有更多的行要计算。
任务并行库拥有管理这样一个过程的所有智能......但我还没有找到这种场景的任何示例,我需要每个线程进行大量数据构建、计算、重置、计算、重置,依此类推,直到完成。
这似乎是一种相当常见的模式...谁能给我举个例子,说明 .NET 4 及更高版本的任务并行库如何支持该模式??
【问题讨论】:
-
这是一种常见的气味,而不是常见的模式。如果您必须“清理和重用”相同的结构,则需要锁定。馊主意。为什么还需要预制结构?有什么好处?要么你必须替换所有值(然后创建一个新值),要么你在谈论常量值。
-
您认为通过重用结构可以解决的实际问题是什么?您是否正在尝试减少内存消耗?分配?您可以使用技术来避免分配(例如,使用正则表达式而不是文件的字符串拆分),或者使用缓冲池来重用缓冲区。
-
我不需要锁定,因为我计划让每个线程构建自己的基础结构实例。把它想象成世界的模型。然后每一行包含该世界中发生的事情(输入),然后需要进行大量分析以确定返回该行的结果。无需锁定。问题是,如果我有 4 个内核和 1000 行,我只想构建世界的基本模型 4 次,并让每个线程清理并重用其模型 250 次。 (我当前的顺序实现只构建了一次世界模型,然后清理和重用了 1000 次。)
-
重用世界模型可以节省时间。想象一下,构建该基本模型需要 10 分钟,使用它来计算一行的结果需要 2 分钟,清理它需要 1 分钟。我的顺序需要 10 + 1000 * (2 + 1) = 3010 分钟。如果我通过排队 1000 个任务以在每个构建模型和分析的 4 个内核上运行来并行化它,那么它将花费 (10 + 2) * 1000 / 4 = 3000 分钟。考虑到额外的开销,净损失。如果我按照我的建议并行化它,那么所有 4 个构建基本模型加上 (2 + 1) * 1000 / 4 = 760 分钟需要 10 分钟......非常接近 4 倍的加速。如何在 TPL 中进行设置?
标签: .net parallel-processing task-parallel-library large-data