我正在尝试实现从 Don Syme 的博客中读到的模式

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

这表明利用异步 I/O 有机会大幅提高性能。我目前正在尝试使用 Array.Parallel.Map 以一种方式“工作”一段代码,看看我是否可以使用 Async.Parallel 以某种方式实现相同的结果,但我真的不了解 Async.Parallel,并且不能得到任何工作。

我有一段代码(为了说明这一点而在下面进行了简化),它成功地检索了一个 cusip 的数据数组。 (例如价格系列)

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

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

因此,这种方法通过互联网连接到我的每只股票(可能多达 3000 个)的数据供应商,并返回一组数组(每只股票 1 个,每个股票的价格序列)一)。诚然,我不明白 Array.Parallel.map 下发生了什么,但我想知道这是否是一种在引擎盖下浪费资源的场景,并且实际上使用异步 I/O 会更快?所以为了测试这一点,我尝试使用 asyncs 来创建这个函数,我认为下面的函数遵循 Don Syme 文章中使用 URL 的模式,但它不会用“let!”编译。
let getStockDataAsync cusip =
    async {  let D = DataProvider()
             let! arr = D.GetData(cusip)
             return arr
          }

我得到的错误是:
这个表达式应该有类型 Async 但这里有类型 obj

它用“let”而不是“let!”编译得很好,但我认为重点是你需要感叹号才能让命令在不阻塞线程的情况下运行。

所以第一个问题真的是,我上面的语法有什么问题,在 getStockDataAsync 中,然后在更高级别,任何人都可以提供一些关于异步 I/O 的额外见解,以及我提出的场景是否会从中受益,使其成为潜在的比 Array.Parallel.map 快多少?非常感谢。

最佳答案

F# 异步工作流允许您实现异步计算,但是,F# 区分了普通计算和异步计算。这种差异由类型系统跟踪。例如,同步下载网页的方法的类型为 string -> string(获取 URL 并返回 HTML),但异步执行相同操作的方法的类型为 string -> Async<string>。在 async 块中,您可以使用 let! 调用异步操作,但必须使用 let 调用所有其他(标准同步)方法。现在,你的例子的问题是 GetData 操作是普通的同步方法,所以你不能用 let! 调用它。

在典型的 F# 场景中,如果要使 GetData 成员异步,则需要使用异步工作流来实现它,因此还需要将其包装在 async 块中。在某个时候,您将到达一个真正需要异步运行某些原始操作的位置(例如,从网站下载数据)。 F# 提供了几个原始异步操作,您可以使用 asynclet! 块调用这些操作,例如 AsyncGetResponse(这是 GetResponse 方法的异步版本)。因此,在您的 GetData 方法中,您将例如编写如下内容:

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) }

总结就是你需要识别一些原始的异步操作(比如等待 web 服务器或等待文件系统),在那个点使用原始异步操作,并将所有使用这些操作的代码包装在 async 块中。如果没有可以异步运行的原始操作,那么您的代码受 CPU 限制,您可以只使用 Parallel.map

我希望这有助于您了解 F# 异步工作流的工作原理。有关更多信息,您可以例如查看 Don Syme's blog post 、关于 asynchronous programming by Robert Pickering 的系列或我的 F# web cast

关于f# - Async.Parallel 还是 Array.Parallel.Map?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2477931/

10-14 01:47