【问题标题】:Parallel I/O using TPL使用 TPL 的并行 I/O
【发布时间】:2012-01-22 19:44:59
【问题描述】:

假设有一个文档 ID 列表,我想从 Web 服务中检索文档。我是 TPL 的新手,对一些我未能通过谷歌搜索的最佳实践感兴趣。

PLINQ 的AsParallel() 不适合在这里,因为它将源 ID 列表分区,从而在单个分区中一一检索文档,我是否正确?

我是否应该使用 LINQ 的 Select() 方法将列表转换为 Task<Document> 列表,然后将其转换为 WaitAll()

Parallel 类和AsParallel() 扩展方法都在下面使用Task<T>,不是吗?是否可以将本地状态传递给代表,就像我将它传递给 Task(Action<Object>, Object) 重载一样?

【问题讨论】:

    标签: .net .net-4.0 parallel-processing task-parallel-library


    【解决方案1】:

    将 AsParallel 用于 IO 是危险的,因为您无法精确控制并行度 (DOP)。您的 IO 设备将具有某个最佳 DOP,但这与 TPL 将使用的不同。

    另外,在调用网络函数时,我发现 TPL 使用的线程数比处理器数多得多。这导致网络过饱和和次优吞吐量。它也可能导致超时。我不会把这样的东西投入生产,因为它的本质是脆弱的。

    TPL 用于选择线程数的算法对我来说并不完全清楚。我认为它会尝试检测添加的线程数是否超过 CPU 数量会增加吞吐量。但恕我直言,它永远不会使用少于 CPU 数量的 CPU。想象 64 个线程正在敲击您的 Web 服务。

    如果您需要精确程度的并行性,我建议您自己创建所需数量的任务/线程。您可以将此代码放入可重用的辅助函数(“ParallelForeachWithExactDOP”)中。

    我的建议:如果您只想并行运行您拥有的所有内容,从而冒着过饱和和超时的风险,您确实可以使用 Select 来一次生成所有任务。仅当您知道任务数量在合理范围内(例如,最多有 10 个文档)时才应该这样做。

    您还可以使用以下技巧:将文档分成 10 个块。然后,对于每个块,您一次生成所有任务并等待所有任务完成。这样,您一次只有 10 个任务在运行。这种方法相当简单。但它会提供次优的吞吐量,因为大多数时候运行的任务少于 10 个,有时甚至没有。认为这是一种简单的初学者技巧。

    【讨论】:

    • 谢谢,很有帮助!就我而言,第三方 API(Web 服务)仅公开 get-by-id 方法,而用户场景允许多个文档检索。所以可能手动任务生成对我来说会更好,特别是如果我不能将本地状态传递给 AsParallel()。
    • 让我提醒您,如果您的呼叫者同时传递许多文档,他们将看到超时。他们也可能看不到超时,但同一 Web 服务的 其他 客户端可能会看到严重的减速。
    【解决方案2】:

    不确定这是并行化的好目标,瓶颈将是常见的客户端网络连接。不能从这里说,但除非您有很多未使用的容量(有占用网络的风险)或者出于某种原因,对一个文档的请求可能会阻塞,以便您可以处理另一个文档,否则不要认为您会得到很多出此。

    通过 Web 服务进行并行化,这将是一个不错的选择。

    【讨论】:

    • 不幸的是我没有太多选择。我的 UI 是 Web 应用程序,因此当我在后端逐一请求文档时,用户可能会看到浏览器超时,而不是尝试并行执行它们,希望第三方服务器可以处理负载。
    • 后端。嗯,我知道你要去哪里。在我开始这样做之前,我想知道,并行会明显更快,如果是这样,我有能力显着增加我对 n 个“文档包”请求的网络需求。我想我会研究某种正在进行的机制,以避免超时。显示要运行的文档数量,然后在它们都存在时启用下一个活动。
    猜你喜欢
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 2013-11-25
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 2015-10-20
    • 1970-01-01
    相关资源
    最近更新 更多