国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

詳解F#異步及并行模式中的并行CPU及I/O計算

開發 后端
本文將討論的是F#異步及并行模式中的并行CPU及I/O計算,隨著Visual Studio 2010的逐步普及,F#自然也成為了大家關注的焦點。

51CTO將持續關注函數式編程語言F#的發展,今天將為大家講述的是F#異步及并行模式中的并行CPU及I/O計算。

最后還是忍不住翻譯文章了。這系列的文章談論的是F#中常見的異步及并行模式,作者為F#語言的主要設計者Don Syme。異步相關的編程是F#語言中最重要的優勢之一(我甚至在考慮“之一”兩個字能否去掉)。F#是一門非常有特色的語言,是一門能夠開闊眼界,改變您編程思路的語言,它經過了幾年設計以及多個預覽之后終于要正式露面了——此刻不上,更待何時。

介紹

F#是一門并行(parallel)及響應式(reactive)語言。這個說法意味著一個F#程序可以存在多個進行中的運算(如使用.NET線程進行F#計算),或是多個等待中的回應(如等待事件或消息的回調函數及代理對象)。

F#的異步表達式是簡化異步及響應式程序編寫的方式之一。在這篇及今后的文章中,我會探討一些使用F#進行異步編程的基本方式──大致說來,它們都是F#異步編程時使用的模式。這里我假設您已經掌握了async的基本使用方式,如入門指南中的內容。

我們從兩個簡單的設計模式開始:CPU異步并行(Parallel CPU Asyncs)和I/O異步并行(Paralle I/O Asyncs)。

本系列的第2部分描述了如何從異步計算或后臺計算單元中獲得結果。

第3部分則描述了F#中輕量級的,響應式的,各自獨立的代理對象。

模式1:CPU異步并行

首先來了解第一個模式:CPU異步并行,這意味著并行地開展一系列的CPU密集型計算。下面的代碼計算的是斐波那契數列,它會將這些計算進行并行地調配:

  1. let rec fib x = if x <= 2 then 1 else fib(x-1) + fib(x-2)  
  2. let fibs =  
  3.     Async.Parallel [ for i in 0..40 -> async { return fib(i) } ]  
  4.     |> Async.RunSynchronously 

結果是:

  1. val fibs : int array =  
  2.      [|1; 1; 2; 3; 5; 8; 13; 21; 34; 55; 89; 144; 233; 377; 610; 987; 1597; 2584;  
  3.        4181; 6765; 10946; 17711; 28657; 46368; 75025; 121393; 196418; 317811;  
  4.        514229; 832040; 1346269; 2178309; 3524578; 5702887; 9227465; 14930352;  
  5.        24157817; 39088169; 63245986; 102334155|] 

上面的代碼展示了并行CPU異步計算模式的要素:

1.“async { … }”用于指定一系列的CPU任務。

2.這些任務使用Async.Parallel進行fork-join式的組合。

在這里,我們使用Async.RunSynchronously方法來執行組合后的任務,這會啟動一個異步任務,并同步地等待其最后結果。您可以使用這個模式來完成各種CPU并行(例如對矩陣乘法進行劃分和并行計算)或是批量處理任務。

模式2:I/O異步并行

現在我們已經展示了在F#中進行CPU密集型并行編程的方式。F#異步編程的重點之一,便是可以用相同的方式進行CPU和I/O密集型的計算。這便是我們的第二種模式:I/O異步并行,即同時開展多個I/O操作(也被稱為overlapped I/O)。例如下面的代碼便并行地請求多個Web頁面,并響應每個請求的回復,再返回收集到的結果。

  1. open System  
  2. open System.Net  
  3. open Microsoft.FSharp.Control.WebExtensions  
  4. let http url =  
  5.     async { let req =  WebRequest.Create(Uri url)  
  6.             use! resp = req.AsyncGetResponse()  
  7.             use stream = resp.GetResponseStream()  
  8.             use reader = new StreamReader(stream)  
  9.             let contents = reader.ReadToEnd()  
  10.             return contents }  
  11.    
  12. let sites = ["http://www.bing.com";  
  13.              "http://www.google.com";  
  14.              "http://www.yahoo.com";  
  15.              "http://www.search.com"]  
  16.    
  17. let htmlOfSites =  
  18.     Async.Parallel [for site in sites -> http site ]  
  19.     |> Async.RunSynchronously 

上面的代碼示例展示了I/O異步并行模式的基礎:

1.“async { … }”用于編寫任務,其中包含了一些異步I/O。

2.這些任務使用Async.Parallel進行fork-join式的組合。

在這里,我們使用Async.RunSynchronously方法來執行組合后的任務,這會啟動一個異步任務,并同步地等待其最后結果。

使用let!(或與它類似的資源釋放指令use!)是進行異步操作的基礎方法。例如:

  1. let! resp = req.AsyncGetResponse() 

上面這行代碼會“響應”一個HTTP GET操作所得到的回復,即async { … }在AsyncGetResponse操作完成之后的部分。然而,在等待響應的過程中并不會阻塞任何.NET或操作系統的線程:只有活動的CPU密集型運算會使用下層的.NET或操作系統線程。與此不同,等待中的響應操作(例如回調函數,事件處理程序和代理對象)資源占用非常少,幾乎只相當于一個注冊好的對象而已。因此,您可以同時擁有數千個甚至數百萬個等待中的響應操作。例如,一個典型的GUI應用程序會注冊一些事件處理程序,而一個典型Web爬蟲會為每個發出的請求注冊一個回調函數。

在上面的代碼中,我們使用了“use!”而不是“let!”,這表示Web請求相關的資源會在變量超出字面的作用域之后得到釋放。

I/O并行的美妙之處在于其伸縮性。在多核的環境下,如果您可以充分利用計算資源,則通常會獲得2倍、4倍甚至8倍的性能提高。而在I/O并行編程中,您可以同時進行成百上千的I/O操作(不過實際的并行效果還要取決于您的操作系統和網絡連接狀況),這意味著10倍、100倍、1000倍甚至更多的性能增強──而這一切在一臺單核的機器上也可以實現。例如,這里有一個使用F#異步功能的示例,而最終它們可以在一個IronPython應用程序中使用。

許多現代應用程序都是I/O密集型應用,因此這些設計模式在實踐中都有很重要的意義。

始于GUI線程,終于GUI線程

這兩個設計模式有個重要的變化,這便是使用Async.StartWithContinuations來代替Async.RunSynchronously方法。在一個并行操作開啟之后,您可以指定三個函數,分別在它成功、失敗或取消時調用。

對于諸如“我想要獲得一個異步操作的結果,但我不能使用RunSynchronously方法”之類的問題,您便應該考慮:

1.使用let!(或use!)把這個異步操作作為更大的異步任務的一部分,

2.使用Async.StartWithContinuations方法執行異步操作

在那些需要在GUI線程上發起異步操作的場景中,Async.StartWithContinuations方法尤其有用。因為,您不會因此阻塞住GUI線程,而且可以在異步操作完成后直接進行GUI的更新。例如,在F# JAOO Tutorial的BingTranslator示例中便使用了這個做法──您可以在本文結尾瀏覽它的完整代碼,不過這里最值得關注的部分則是在點擊“Translate”按鈕之后發生的事情:

  1. button.Click.Add(fun args ->  
  2.    
  3.     let text = textBox.Text  
  4.     translated.Text <- "Translating..." 
  5.    
  6.     let task =  
  7.         async { let! languages = httpLines languageUri  
  8.                 let! fromLang = detectLanguage text  
  9.                 let! results = Async.Parallel [for lang in languages -> translateText (text, fromLang, lang)]  
  10.                 return (fromLang,results) }  
  11.    
  12.     Async.StartWithContinuations(   
  13.         task,  
  14.         (fun (fromLang,results) ->  
  15.             for (toLang, translatedText) in results do  
  16.                 translated.Text <- translated.Text + sprintf "\r\n%s --> %s: \"%s\"" fromLang toLang translatedText),  
  17.         (fun exn -> MessageBox.Show(sprintf "An error occurred: %A" exn) |> ignore),  
  18.         (fun cxn -> MessageBox.Show(sprintf "A cancellation error ocurred: %A" cxn) |> ignore))) 

高亮的部分,尤其是在async塊里的部分,展示了使用Async.Parallel將一種語言并行地翻譯成多種語言的做法。這個異步組合操作由Async.StartWithContinuations發起,它會在遇到第一個I/O操作時立即返回(譯注:存疑,為什么是在遇上I/O操作才返回?),并指定了三個函數,分別在異步操作的成功,失敗或取消時調用。以下是任務完成后的截圖(不過在此不保證翻譯的準確性……):

調用截圖

Async.StartWithContinuations有一個重要的特性:如果異步操作由GUI線程發起(例如一個SynchronizationContext.Current不為null的線程),那么操作完成后的回調函數也是在GUI線程中調用的。這使GUI更新操作變的十分安全。F#異步類庫允許您組合多個I/O任務,并在GUI線程中直接使用,而無需您親自從后臺線程中更新GUI元素。在以后的文章中我們會進行更詳細地解釋。

關于Async.Parallel工作方式:

在執行時,由Async.Parallel組合而成的異步操作會通過一個等待計算的隊列來逐步發起。與大部分進行異步處理的類庫一樣,它在內部使用的是QueueUserWorkItem方法。當然,我們也有辦法使用分離的隊列,在以后的文章中我們會進行一些討論。

Async.Parallel方法并沒有什么神奇之處,您也完全可以使用Microsoft.FSharp.Control.Async類庫中的其他原語來定義您自己的異步組合方式──例如Async.StartChild方法。我們會在以后的文章中討論這個話題。

更多示例

在F# JAOO Tutorial包含多個使用這些模式的示例代碼:

BingTranslator.fsx與BingTranslatorShort.fsx:使用F#調用REST API,它們與其他基于Web的HTTP服務的調用方式十分類似。文末包含了示例的完整代碼。

AsyncImages.fsx:并行磁盤I/O及圖像處理。

PeriodicTable.fsx:調用一個Web服務,并行地獲取原子質量。

本文模式的限制

上文介紹的兩個并行模式有一些限制。很明顯,使用Async.Parallel生成的異步操作在執行時十分“安靜”──比方說,它們無法返回進度或部分的結果。為此,我們需要構建一個更為“豐富”的對象,它會在部分操作完成之后觸發一些事件。在以后的文章中我們會來關注這樣的設計模式。

此外,Async.Parallel只能處理固定數量的任務。在以后的文章中,我們會遇到很多一邊處理一邊生成任務的情況。換個方式來看,即Async.Parallel無法處理即時獲得的消息──例如,除了取消任務之外,一個代理對象的工作進度是可以得到控制的。

總結

CPU異步并行與I/O異步并行,是F#異步編程中最為簡單的兩種設計模式,而簡單的事物往往也是非常重要而強大的。請注意,兩種模式的不同之處,僅僅在于I/O并行使用了包含了I/O請求的async塊,以及一些額外的CPU任務,如創建請求對象及后續處理。

在今后的文章里,我們會關注F#中其他一些并行及響應式編程方面的設計方式,包括:

  • 從GUI線程中發起異步操作
  • 定義輕量級異步代理對象
  • 使用async定義后臺工作程序
  • 使用async構建.NET任務
  • 使用async調用.NET的APM模式
  • 取消異步操作

BingTranslator代碼示例

以下是BingTranslator的示例代碼,在運行時您需要申請一個Live API 1.1 AppID。請注意,這個示例需要根據Bing API 2.0進行適當調整,至少在2.0中已經不包含這里的語言檢測API了──不過這些代碼仍然是不錯的示例:

 

  1. open System  
  2. open System.Net  
  3. open System.IO  
  4. open System.Drawing  
  5. open System.Windows.Forms  
  6. open System.Text  
  7.    
  8. /// A standard helper to read all the lines of a HTTP request. The actual read of the lines is  
  9. /// synchronous once the HTTP response has been received.  
  10. let httpLines (uri:string) =  
  11.   async { let request = WebRequest.Create uri  
  12.           use! response = request.AsyncGetResponse()           
  13.           use stream = response.GetResponseStream()  
  14.           use reader = new StreamReader(stream)  
  15.           let lines = [ while not reader.EndOfStream do yield reader.ReadLine() ]  
  16.           return lines }  
  17.    
  18. type System.Net.WebRequest with  
  19.    
  20.     /// An extension member to write content into an WebRequest.  
  21.     /// The write of the content is synchronous.  
  22.     member req.WriteContent (content:string) =  
  23.         let bytes = Encoding.UTF8.GetBytes content  
  24.         req.ContentLength <- int64 bytes.Length  
  25.         use stream = req.GetRequestStream()  
  26.         stream.Write(bytes,0,bytes.Length)  
  27.    
  28.     /// An extension member to read the content from a response to a WebRequest.  
  29.     /// The read of the content is synchronous once the response has been received.  
  30.     member req.AsyncReadResponse () =  
  31.         async { use! response = req.AsyncGetResponse()  
  32.                 use responseStream = response.GetResponseStream()  
  33.                 use reader = new StreamReader(responseStream)  
  34.                 return reader.ReadToEnd() }  
  35.    
  36. #load @"C:\fsharp\staging\docs\presentations\2009-10-04-jaoo-tutorial\BingAppId.fs"  
  37. //let myAppId = "please set your Bing AppId here" 
  38.    
  39.    
  40. /// The URIs for the REST service we are using  
  41. let detectUri       = "http://api.microsofttranslator.com/V1/Http.svc/Detect?appId=" + myAppId  
  42. let translateUri    = "http://api.microsofttranslator.com/V1/Http.svc/Translate?appId=" + myAppId + "&" 
  43. let languageUri     = "http://api.microsofttranslator.com/V1/Http.svc/GetLanguages?appId=" + myAppId  
  44. let languageNameUri = "http://api.microsofttranslator.com/V1/Http.svc/GetLanguageNames?appId=" + myAppId  
  45.    
  46. /// Create the user interface elements  
  47. let form       = new Form (Visible=true, TopMost=true, Height=500, Width=600)  
  48. let textBox    = new TextBox (Width=450, Text="Enter some text", Font=new Font("Consolas", 14.0F))  
  49. let button     = new Button (Text="Translate", Left = 460)  
  50. let translated = new TextBox (Width = 590, Height = 400, Top = 50, ScrollBars = ScrollBars.Both, Multiline = true, Font=new Font("Consolas", 14.0F))  
  51.    
  52. form.Controls.Add textBox  
  53. form.Controls.Add button  
  54. form.Controls.Add translated  
  55.    
  56.    
  57. /// An async method to call the language detection API  
  58. let detectLanguage text =  
  59.   async { let request = WebRequest.Create (detectUri, Method="Post", ContentType="text/plain")  
  60.           do request.WriteContent text  
  61.           return! request.AsyncReadResponse() }  
  62.    
  63. /// An async method to call the text translation API  
  64. let translateText (text, fromLang, toLang) =  
  65.   async { let uri = sprintf "%sfrom=%s&to=%s" translateUri fromLang toLang  
  66.           let request = WebRequest.Create (uri, Method="Post", ContentType="text/plain")  
  67.           request.WriteContent text  
  68.           let! translatedText = request.AsyncReadResponse()  
  69.           return (toLang, translatedText) }  
  70.    
  71. button.Click.Add(fun args ->  
  72.    
  73.     let text = textBox.Text  
  74.     translated.Text <- "Translating..." 
  75.    
  76.     let task =  
  77.         async { /// Get the supported languages  
  78.                 let! languages = httpLines languageUri  
  79.                 /// Detect the language of the input text. This could be done in parallel with the previous step.  
  80.                 let! fromLang = detectLanguage text  
  81.                 /// Translate into each language, in parallel  
  82.                 let! results = Async.Parallel [for lang in languages -> translateText (text, fromLang, lang)]  
  83.                 /// Return the results  
  84.                 return (fromLang,results) }  
  85.    
  86.     /// Start the task. When it completes, show the results.  
  87.     Async.StartWithContinuations(   
  88.         task,  
  89.         (fun (fromLang,results) ->  
  90.             for (toLang, translatedText) in results do  
  91.                 translated.Text <- translated.Text + sprintf "\r\n%s --> %s: \"%s\"" fromLang toLang translatedText),  
  92.         (fun exn -> MessageBox.Show(sprintf "An error occurred: %A" exn) |> ignore),  
  93.         (fun cxn -> MessageBox.Show(sprintf "A cancellation error ocurred: %A" cxn) |> ignore))) 

 

責任編輯:彭凡 來源: 博客園
相關推薦

2010-03-16 09:09:04

F#

2010-03-26 19:03:19

F#異步并行模式

2010-03-26 18:31:59

F#異步并行模式

2009-08-19 09:42:34

F#并行排序算法

2012-03-12 12:34:02

JavaF#

2009-08-13 17:25:21

F#入門

2010-04-07 16:51:59

F#

2012-04-10 10:04:26

并行編程

2009-09-04 09:39:15

Visual Stud

2010-04-06 15:20:56

ASP.NET MVC

2019-12-03 09:00:59

Oracle數據庫等待事件

2015-08-10 14:39:46

Java 操作建議

2009-11-16 09:05:46

CodeTimer

2009-12-18 09:38:27

.NET 4.0并行計

2013-12-18 17:29:10

多核并行

2010-04-07 09:46:05

2010-01-26 08:25:06

F#語法F#教程

2010-03-26 19:22:08

F#代理

2011-02-25 09:16:00

SQLSQL Server IO

2023-11-12 17:19:07

并行并發場景
點贊
收藏

51CTO技術棧公眾號

羞羞网站在线看| 看黄网站在线| 国产精品久久久久久久久久久久| 精品久久久久久亚洲精品| 日韩一级免费| 91丨九色丨蝌蚪丨老版| 超级白嫩亚洲国产第一| 成人福利片网站| 亚洲一区二区三区四区| 精品亚洲成a人片在线观看| 成人av免费电影网站| 久久视频在线| 在线成人直播| 国产一区91精品张津瑜| 亚洲欧美激情插| 亚洲狠狠丁香婷婷综合久久久| 欧美一区二区三区啪啪| 成人福利视频在线观看| 亚欧黄色av| 91亚洲资源网| 精品日韩一区二区三区免费视频| 国产精品一区二区a| 国内av免费| 欲香欲色天天天综合和网| 蜜桃视频第一区免费观看| 欧美性猛交丰臀xxxxx网站| 久久av一区二区三区亚洲| 在线观看欧美理论a影院| 久久免费美女视频| 久久国产精品偷| 大西瓜av在线| 成人影欧美片| 狠狠综合久久| 亚洲妇熟xx妇色黄| 午夜精品在线观看| 成人在线播放网站| 精品国产三级a在线观看| 91超碰中文字幕久久精品| 91视频免费版污| 国产蜜臀在线| 九九视频精品免费| www.亚洲一区| 欧美日韩精品综合| 中文字幕21页在线看| 欧美日本免费| 国产日韩欧美高清| 国内精品久久久久久久久| 三级短视频在线| 欧美大片91| 亚洲精品美女在线观看播放| 亚洲欧洲国产日韩精品| 欧美久久久网站| 国产亚洲精品免费| 国产精品欧美一区二区三区奶水 | 国内久久精品| 91首页免费视频| 欧美专区福利在线| 国产成人久久婷婷精品流白浆| 精品一区二区三区亚洲| 欧美国产视频在线| 奇门遁甲1982国语版免费观看高清 | 91精品国产91久久久久游泳池 | 99久久精品久久久久久ai换脸| 国产福利久久| 国产精品偷拍| 一区二区三区四区中文字幕| 亚洲男人7777| 成人短视频在线| 玛雅亚洲电影| 毛片av一区二区| 欧美最猛黑人xxxx黑人猛叫黄| 日本私人网站在线观看| 国产精品一卡| 97精品国产97久久久久久免费 | 日韩大片在线| 成人偷拍自拍| 美国欧美日韩国产在线播放| 欧美疯狂做受xxxx高潮| 麻豆网站在线| 中文一区一区三区高中清不卡| 日韩最新中文字幕| 久久久久99| 亚洲人精选亚洲人成在线| 麻豆mv在线观看| 7777精品伊人久久久大香线蕉完整版| 色姑娘综合av| 欧美亚洲自偷自偷| 国产精品免费看一区二区三区| 国产极品在线观看| 中文字幕av一区二区| a欧美人片人妖| 亚洲黄色小视频| 日本福利在线| 91精品蜜臀在线一区尤物| 色老板视频在线观看| 亚洲成人一区二区在线观看| 含羞草www国产在线视频| 日韩高清av一区二区三区| h片视频在线观看| 国产专区一区二区| 日韩毛片视频| 日韩小视频在线观看| 最近97中文超碰在线| 色哟哟日韩精品| 顶级网黄在线播放| 免费高清一区二区三区| 久久久国产精品一区| 色综合久久中文| 色噜噜色狠狠狠狠狠综合色一| 欧美激情综合在线| 4kfree性满足欧美hd18| 日韩在线中文视频| 精品少妇av| 在线观看欧美一区| 一区二区三区在线免费| 桃子视频成人app| 狠狠干视频网站| 日本一区二区三区国色天香| 欧美电影在线观看网站| 蜜桃麻豆www久久国产精品| 老司机一区二区三区| 国产小视频免费在线观看| 77777亚洲午夜久久多人| 91原创在线视频| 婷婷成人综合| 91久久青草| 国产三级视频在线| 欧美黑人巨大精品一区二区| 国产精品一区2区| 欧美日韩在线精品一区二区三区激情综合 | 夜夜爽99久久国产综合精品女不卡| 久久免费视频一区| 91国内精品白嫩初高生| 亚洲一区二区蜜桃| 欧美色图12p| 国产suv精品一区二区三区| 在线观看av免费| 国产精品区一区二区三含羞草| 国产亚洲精品aa| 亚洲区小说区| shkd中文字幕久久在线观看| 欧美劲爆第一页| 欧美日韩国产另类不卡| 91精品啪在线观看国产18| 成年人免费看的视频| 中文字幕在线看视频国产欧美在线看完整| 男人的天堂亚洲| 成人三级网址| 国产亚洲精品久久飘花| 日韩综合视频在线观看| 久久影视一区二区| 国产成人手机高清在线观看网站| 大j8黑人w巨大888a片| 豆国产97在线| 日韩三级成人av网| 国产日韩欧美精品一区| **女人18毛片一区二区| 欧洲美女精品免费观看视频 | 国内外激情在线| 亚洲一区二区在线| 日韩中文字幕在线看| 亚洲精品欧美二区三区中文字幕| 蜜乳av一区二区| 高清电影在线观看免费| 久草在线在线| 日韩少妇内射免费播放| 91原创国产| 亚洲男人的天堂在线播放| 欧美一三区三区四区免费在线看| 国产精品精品国产色婷婷| 在线成人激情| 成人国产精品久久| 久久免费资源| 加勒比视频一区| 三级无遮挡在线观看| 视频在线观看免费高清| 欧美日韩一区二区在线免费观看| 欧美日韩一区二| 欧美激情一区二区三区久久久| 亚洲黄色免费三级| 日韩av在线网| 久久久久女教师免费一区| 黑人巨大精品欧美一区二区免费 | 一区二区三区欧美亚洲| 香港久久久电影| √天堂资源地址在线官网| 国精品产品一区| 韩国女主播成人在线| 成年人午夜久久久| 国产精品一区毛片| 亚洲精品视频啊美女在线直播| 无码少妇一区二区三区| 9lporm自拍视频区在线| 色在线免费观看| 精品深夜福利视频| 久久一区91| 欧亚精品一区| 欧美xxx在线观看| 亚洲精品中文字幕| 网址你懂得在线观看|