F#:异步、任务和 PLINQ,天哪! [英] F#: Asynch and Tasks and PLINQ, oh my!

查看:24
本文介绍了F#:异步、任务和 PLINQ,天哪!的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当F#出来时,我将在异步/并行编程领域有一个财富的尴尬.这个问题的答案很好地描述了任务、并行 LINQ 和反应式框架之间的差异,但我想知道异步工作流如何准确地融入图片.

When F# comes out, I am going to have an embarrassment of riches in the asynchronous/parallel programming area. An answer to this question does a pretty good job of describing the differences between Tasks, Parallel LINQ, and Reactive Framework, but I was wondering how asynchronous workflows fit into the picture, exactly.

如果我错了,请纠正我,但据我所知,异步工作流将是处理 IO 绑定操作的最简单方法,尤其是那些定义了 AsynchXxx 方法或遵循 BeginXxx/EndXxx 模式的操作.另一个优点是异步工作流是可组合的,并且可以从其他异步工作流中构建出来 - 这可以为程序的结构方式提供很大的灵活性.

Please correct me if I'm wrong, but as I understand it asynch workflows are going to be the easiest way to work with IO-bound operations, particularly those that have an AsynchXxx method defined, or follow the BeginXxx/EndXxx pattern. Another advantage is that asynch workflows are composable, and can be built out of other asynch workflows - which can allow for a great deal of flexibility in the way a program is structured.

我想我需要帮助的是了解在什么情况下我会在 F# 代码中选择任务或 PLINQ 而不是异步工作流.我相信我读过任务并行库有更复杂的方法来平衡内核之间的负载.如果这是真的,那么对于需要并行操作的纯 CPU 绑定操作,任务可能是更好的选择.另一方面,PLINQ 似乎主要是一种并行化处理序列的现有代码的便捷方式.

I guess what I need help with is understanding under what circumstances I would choose Tasks or PLINQ over asynchronous workflows, in F# code. I believe I read that the Task Parallel Library has more sophisticated ways to balance the load across cores. If that's true, then Tasks might be a better choice for purely CPU-bound operations that need to operate in parallel. PLINQ, on the other hand, seems to be mainly a convenient way to parallelize existing code that works with sequences.

最后,假设我对每种方法的优势的理解是正确的,是否有可能或建议将它们结合起来?例如,也许可以从异步工作流中组合一系列操作,然后在执行之前将它们转换为任务.如果可能的话 - 或者甚至是一个好主意.

Finally, assuming that my understanding of the strengths of each approach is correct, is it ever possible or advisable to combine them? For example, perhaps one could compose a series of operations out of asynchronous workflows, and then transform them to Tasks prior to execution. If that's possible - or even a good idea.

推荐答案

参见 任务并行库与异步工作流.

我将基本知识总结如下:

I'd summarize the basics as follows:

任务并行库:允许多个工作单元在多个内核上高效运行,包括相对简单的场景,例如生成多个线程以并行执行类似计算以及更复杂的计算他们自己最终也会产生额外的任务.使用改进的 .NET 4.0 线程池和工作窃取队列来确保所有内核都保持忙碌.

Task Parallel Library: Allows multiple units of work to run efficiently on multiple cores, including relatively simple scenarios such as spawning multiple threads to do similar computations in parallel as well as more complicated operations where the computations themselves also end up spawning additional tasks. Uses the improved .NET 4.0 threadpool and work stealing queues to ensure that all cores are kept busy.

异步工作流:允许异步计算在不占用不需要的线程的情况下运行,并在结果可用时启动回调.

Async workflows: Allows asynchronous computations to run without occupying unneeded threads, initiating callbacks when results are available.

PLINQ:使用 PLINQ 编写的代码最终通过 TPL 运行,但这是一个更好的代码接口,可以使用 LINQ 查询轻松表达(例如对数组中的每个项目执行单个操作并行数据).

PLINQ: Code written using PLINQ ends up running via the TPL, but this is a nicer interface for code which is easily expressed using LINQ queries (e.g. doing a single operation on each item in an array of data in parallel).

请注意,异步工作流可以使用 StartAsTask 方法转换为任务,任务可以使用 Async.AwaitTask 转换为 Asyncs> 方法,因此可以桥接这些技术,尽管它们的目标场景略有不同.

Note that async workflows can be converted to Tasks using the StartAsTask method, and Tasks can be converted to Asyncs using the Async.AwaitTask method, so it's possible to bridge the technologies, although they do aim at slightly different target scenarios.

对我来说,经验法则是,如果您在不同的线程上主动进行大量计算,您将需要使用 TPL(可能通过 PLINQ 或 F# 等效项,例如 PSeq 模块),而如果您尝试执行大量 IO(无论是否并行),则应使用异步工作流.因此,光线追踪器将使用 TPL 来启动并行渲染每个像素(或扫描线)的任务,从而最大限度地提高计算机上的可用计算能力.但是下载一堆网页将通过异步工作流完成,因为在内核之间传播的计算量并不多;当结果出来时,你只需要得到操作系统的通知.

To me, the rule of thumb would be that if you're actively doing lots of computation on different threads, you'll want to use the TPL (possibly via PLINQ or an F# equivalent such as the PSeq module), whereas if you're trying to do lots of IO (whether parallel or not), you should use asynch workflows. So a raytracer would use TPL to kick off tasks to render each pixel (or scanline) in parallel, maximizing the available computing power on your computer. But downloading a bunch of webpages would be done with async workflows since there's not much computation to spread among cores; you just need to be notified by the OS when the results have come in.

这篇关于F#:异步、任务和 PLINQ,天哪!的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆