Async.Parallel或Array.Parallel.Map?

问题描述 投票:9回答:2

我想实现我从唐赛姆的博客阅读模式

(Qazxswpoi)

这表明,有从利用异步I / O大量提高性能的机会。目前我正在试图采取这一“工程”的一种方式,用Array.Parallel.Map一段代码,看看我是否能使用Async.Parallel某种方式达到同样的效果,但我真的不明白Async.Parallel,并不能得到任何工作。

我有一段代码(下面简化为说明这一点),其成功地检索数据的数组,一个CUSIP。 (A价格序列,例如)

https://blogs.msdn.microsoft.com/dsyme/2010/01/09/async-and-parallel-design-patterns-in-f-parallelizing-cpu-and-io-computations/

因此,这种方法contructs数组的数组,通过使在互联网上我的数据供应商每只股票的连接(这可能是多达3000),并返回我阵列(1元股票的阵列,具有价格序列的每个一)。我固然不明白那张Array.Parallel.map下,但我想如果这是那里的引擎盖下的资源浪费的情形,它实际上可以使用异步I / O更快?因此,测试了这一点,我试图让使用异步操作这个功能,我认为下面的功能使用如下的URL在Don赛姆的文章的模式,但它不会与“放!”编译。

let getStockData cusip = 
    let D = DataProvider()
    let arr = D.GetPriceSeries(cusip)
    return arr

let data = Array.Parallel.map (fun x -> getStockData x) stockCusips

我得到的错误是:这表达预计将有型异步<'一>但这里的类型为OBJ

它编译罚款与“让”,而不是“让!”,但我以为整点是,你需要的感叹号,以便命令不阻塞线程运行。

因此,第一个真正的问题是,这有什么错我的语法上面,在getStockDataAsync,然后在一个较高的水平,任何人都可以提供关于台异步I / O,以及是否我已经提出会从中受益的情况下一些额外的洞察力,使之成为可能多少,比Array.Parallel.map快得多?非常感谢。

f#
2个回答
21
投票

F#异步工作流,可以实现异步计算,然而,F#使得通常的计算和异步计算之间的区别。这种差异是由类型系统追踪。例如该下载网页,是同步的有型let getStockDataAsync cusip = async { let D = DataProvider() let! arr = D.GetData(cusip) return arr } (以URL并返回HTML)的方法,但做同样的事情异步有型string -> string的方法。在string -> Async<string>块,你可以使用async调用异步操作,但所有其他(标准同步)方法必须使用let!被调用。现在,你的榜样的问题是,let操作是普通的同步方法,所以你不能用GetData调用它。

在典型的F#的情况下,如果你想使let!成员异步的,你需要使用异步工作流程来实现它,所以你还需要将其包装在GetData块。在某些时候,你会到达一个位置,你真的需要异步运行一些基本操作(例如,从网站上下载数据)。 F#提供了可以从async块使用async调用诸如let!(这是AsyncGetResponse方法的异步版本)几个原始异步操作。所以,在你GetResponse方法,你就如写的是这样的:

GetData

总结是,你需要确定一些基本的异步操作(如等待Web服务器或文件系统),在这一点上使用原始的异步操作,敷在let GetData (url:string) = async { let req = WebRequest.Create(url) let! rsp = req.AsyncGetResponse() use stream = rsp.GetResponseStream() use reader = new System.IO.StreamReader(stream) let html = reader.AsyncReadToEnd() return CalculateResult(html) } 块使用这些操作的所有代码。如果有可以异步运行,没有原始的操作,那么你的代码是CPU绑定的,你可以只使用async

我希望这可以帮助您了解F#异步工作流程是如何工作的。欲了解更多信息,例如,您可以看看Parallel.map,一系列关于Don Syme's blog post,还是我asynchronous programming by Robert Pickering


7
投票

@Tomas已经有一个伟大的答案。我只想说,除了一对夫妇位。

为F#异步操作的成语是命名与“异步”前缀的方法(F# web cast,不AsyncFoo;后者是已被其他.NET技术成语)。所以,你的功能应该是FooAsyncgetStockData

内部的异步工作流程,只要您使用asyncGetStockData代替let!let代替do!的,右边的东西应该有类型do而不是Async<T>。基本上你需要为了在工作流程的这一点“走出去异步”现有的异步计算。每个T本身将是要么其他一些Async<T>工作流程,否则异步“原始”。的原语的F#库经由async{...}或其使得能够限定开始计算,注册一个I / O回调,释放线程,然后重新启动计算的低级别的细节时获取调用回Async.FromBeginEnd定义的或在用户代码创建。所以,你必须“垂直”异步一路下跌到一些真正的,异步I / O基元以获得异步I / O的全部好处。

© www.soinside.com 2019 - 2024. All rights reserved.