Async and Parallel Programming in F#<br />Matthew Podwysocki<br />Senior Consultant<br />http://codebetter.com/<br />@matt...
Agenda<br />F# in 15 Minutes<br />Why is concurrent programming so hard?<br />What can F# do to help?<br />
...a functional, object-oriented, imperative and explorative programming language for .NET with influences from OCaml, C#,...
F# in 15 Minutes – The Facts<br />F# is a general purpose .NETlanguage<br />F# is a multi-paradigm language<br />F# is a s...
F# in 15 Minutes - The Syntax<br />binding names to values<br />let<br />lets = &quot;Hello World&quot;<br />let (x, y) = ...
F# in 15 Minutes - The Syntax<br />functions as values<br />fun<br />let square x = x * x<br />let squares = List.map (fun...
F# in 15 Minutes – The Syntax<br />|&gt;<br />bringing order to chaos<br />let (|&gt;) x f = f x<br />letsumOfSquares = <b...
F# in 15 Minutes – The Syntax<br />discriminated unions<br />type<br />type Suit = | Spade | Heart | Club | Diamond<br />t...
F# in 15 Minutes – The Syntax<br />pattern matching<br />match<br />letcardValue (Card(s,r)) =<br />match r with<br />  | ...
Concurrent programming<br />with shared state…<br />Is really hard!<br />Microsoft Confidential<br />
Shared State Gives Us…<br />Race conditions!<br />Obscure error messages!<br />Late night debugging!<br />Locks, mutexes a...
How Can F# Help Us?<br />Granularity<br />Purity<br />Immutability<br />Libraries<br />
In Praise of Immutability<br />Immutable objects<br />... can be relied upon<br />... can transfer between threads<br />.....
There is no silver bullet<br />
Concurrency Styles<br />Asynchronous Programming<br />Parallel Programming<br />Data<br />Task<br />Actor Model Concurrenc...
Asynchronous Programming<br />
publicstaticvoidProcessImagesInBulk()<br />{<br />Console.WriteLine(&quot;Processing images...  &quot;);<br />long t0 = En...
letProcessImageAsynci =<br />async { useinStream = File.OpenRead(sprintf&quot;Image%d.tmp&quot;i)<br />let! pixels = inStr...
Read stream<br />asynchronously<br />letProcessImageAsynci =<br />async { useinStream = File.OpenRead(sprintf&quot;Image%d...
letgetHtml (url:string) =<br />async { let request = WebRequest.Createurl<br />use! response = request.AsyncGetResponse()<...
How does it work?<br />Success Continuation<br />Async&lt;T&gt;<br />Execution Request<br />Exception Continuation<br />Ca...
Anatomy of an Async Operation<br />Async operations<br />Begin/End<br />typeSystem.Net.WebRequestwith<br />memberthis.Asyn...
What Do We Get For Free?<br />Code that makes sense<br />Exception propagation<br />Cancellation checking<br />Simple reso...
Twitter Example<br />
Parallel Programming<br />Task Parallel<br />Data Parallel<br />
Data Parallel ProgrammingPLINQ<br />Enable F# developers to leverage parallel hardware<br />Abstracts away parallelism det...
Task Parallel Programming<br />Enable F# developers to create tasks in parallel<br />letcomputeHash path algorithm =<br />...
Task Parallel + Async Workflows<br />TPL Tasks integrated in .NET 4.0 Async Workflows<br />Integrate with pre-defined task...
Bing Translator Example<br />
Actor Model Concurrency<br />Lots of little tasks<br />Each process does one task<br />Ant Colony<br />Ants are processes ...
Actor Model in Action…<br />let (&lt;--) (m:&apos;aMailboxProcessor) msg = m.Post(msg)<br />typePinger = Pong<br />typePon...
Actor Model in Action…<br />letpinger count pong =<br />  newMailboxProcessor&lt;Pinger&gt;(funinbox -&gt;<br />    let re...
Web Crawling Example<br />
Ant Colony Example<br />
High Performance Computing<br />MPI.NET<br />Dryad/DryadLINQ<br />
What’s in Store for 2010?<br />
Ways to Learn F#<br />http://www.fsharp.net<br />F# Interactive (FSI)<br />Language Specification<br />F# Team Blogs<br />...
Books about F#<br />
Resources - Blogs<br />Don Symehttp://blogs.msdn.com/dsyme/<br />Luke Hobanhttp://blogs.msdn.com/lukeh/<br />Brian McNamar...
Upcoming SlideShare
Loading in …5
×

Async and Parallel F#

5,102 views

Published on

A look at asynchronous and parallel programming in F# given at the F# User Group on 8/3/2009

Published in: Technology
0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,102
On SlideShare
0
From Embeds
0
Number of Embeds
29
Actions
Shares
0
Downloads
0
Comments
0
Likes
10
Embeds 0
No embeds

No notes for slide
  • What is the Problem?Multithreaded programming is hard todayDoable by only a subgroup of senior specialistsParallel patterns are not prevalent, well known, nor easy to implementSo many potential problemsRaces, deadlocks, livelocks, lock convoys, cache coherency overheads, lost event notifications, broken serializability, priority inversion, and so on…Businesses have little desire to go deepBest developers should focus on business value, not concurrencyNeed simple ways to allow all developers to write concurrent code
  • Async and Parallel F#

    1. 1. Async and Parallel Programming in F#<br />Matthew Podwysocki<br />Senior Consultant<br />http://codebetter.com/<br />@mattpodwysocki<br />
    2. 2. Agenda<br />F# in 15 Minutes<br />Why is concurrent programming so hard?<br />What can F# do to help?<br />
    3. 3. ...a functional, object-oriented, imperative and explorative programming language for .NET with influences from OCaml, C#, Haskell and Erlang<br />Hi! I’m F#<br />
    4. 4.
    5. 5. F# in 15 Minutes – The Facts<br />F# is a general purpose .NETlanguage<br />F# is a multi-paradigm language<br />F# is a statically-typed language<br />
    6. 6. F# in 15 Minutes - The Syntax<br />binding names to values<br />let<br />lets = &quot;Hello World&quot;<br />let (x, y) = (45, 54)<br />let answer = x + y<br />let numbers = [1 .. 10]<br />let odds = [1; 3; 5; 7; 9]<br />let square x = x * x<br />let squareOf4 = square 4<br />
    7. 7. F# in 15 Minutes - The Syntax<br />functions as values<br />fun<br />let square x = x * x<br />let squares = List.map (fun x -&gt; x * x) [1..10]<br />let squares = List.map square [1..10]<br />Operators are functions too!<br />
    8. 8. F# in 15 Minutes – The Syntax<br />|&gt;<br />bringing order to chaos<br />let (|&gt;) x f = f x<br />letsumOfSquares = <br /> List.sum (List.map square [1..10])<br />letsumOfSquares = [1..10] <br /> |&gt; List.map square<br /> |&gt; List.sum<br />&lt;|<br />&gt;&gt;<br />&lt;&lt;<br />See also:<br />
    9. 9. F# in 15 Minutes – The Syntax<br />discriminated unions<br />type<br />type Suit = | Spade | Heart | Club | Diamond<br />type Rank = | Ace | King | Queen | Jack<br /> | Value ofint<br />type Card = Card of Suit * Rank<br />Microsoft Confidential<br />
    10. 10. F# in 15 Minutes – The Syntax<br />pattern matching<br />match<br />letcardValue (Card(s,r)) =<br />match r with<br /> | Ace -&gt; 11<br /> | King | Queen | Jack -&gt; 10<br /> | Value(x) -&gt; x<br />let (x, y) = (&quot;x&quot;, &quot;y&quot;)<br />let [a; b] = [1 ; 2]<br />Microsoft Confidential<br />
    11. 11. Concurrent programming<br />with shared state…<br />Is really hard!<br />Microsoft Confidential<br />
    12. 12. Shared State Gives Us…<br />Race conditions!<br />Obscure error messages!<br />Late night debugging!<br />Locks, mutexes and semaphores, oh my!<br />Microsoft Confidential<br />
    13. 13. How Can F# Help Us?<br />Granularity<br />Purity<br />Immutability<br />Libraries<br />
    14. 14. In Praise of Immutability<br />Immutable objects<br />... can be relied upon<br />... can transfer between threads<br />... can be aliased safely<br />... lead to (different) optimization opportunities<br />
    15. 15. There is no silver bullet<br />
    16. 16. Concurrency Styles<br />Asynchronous Programming<br />Parallel Programming<br />Data<br />Task<br />Actor Model Concurrency<br />
    17. 17. Asynchronous Programming<br />
    18. 18. publicstaticvoidProcessImagesInBulk()<br />{<br />Console.WriteLine(&quot;Processing images... &quot;);<br />long t0 = Environment.TickCount;<br />NumImagesToFinish = numImages;<br />AsyncCallbackreadImageCallback = <br />newAsyncCallback(ReadInImageCallback);<br />for (inti = 0; i &lt; numImages; i++)<br /> {<br />ImageStateObject state = newImageStateObject();<br />state.pixels = newbyte[numPixels];<br />state.imageNum = i;<br />FileStreamfs = newFileStream(ImageBaseName + i + &quot;.tmp&quot;,<br />FileMode.Open, FileAccess.Read, FileShare.Read, 1, true);<br />state.fs = fs;<br />fs.BeginRead(state.pixels, 0, numPixels, readImageCallback,<br /> state);<br /> }<br />boolmustBlock = false;<br />lock (NumImagesMutex)<br /> {<br />if (NumImagesToFinish &gt; 0)<br />mustBlock = true;<br /> }<br />if (mustBlock)<br /> {<br />Console.WriteLine(&quot;All worker threads are queued. &quot; +<br />&quot; Blocking until they complete. numLeft: {0}&quot;,<br />NumImagesToFinish);<br />Monitor.Enter(WaitObject);<br />Monitor.Wait(WaitObject);<br />Monitor.Exit(WaitObject);<br /> }<br />long t1 = Environment.TickCount;<br />Console.WriteLine(&quot;Total time processing images: {0}ms&quot;,<br /> (t1 - t0));<br />}<br />publicstaticvoidReadInImageCallback(IAsyncResultasyncResult)<br />{<br />ImageStateObject state = (ImageStateObject)asyncResult.AsyncState;<br />Streamstream = state.fs;<br />intbytesRead = stream.EndRead(asyncResult);<br />if (bytesRead != numPixels)<br />thrownewException(String.Format<br /> (&quot;In ReadInImageCallback, got the wrong number of &quot; +<br />&quot;bytes from the image: {0}.&quot;, bytesRead));<br />ProcessImage(state.pixels, state.imageNum);<br />stream.Close();<br />FileStreamfs = newFileStream(ImageBaseName + state.imageNum +<br />&quot;.done&quot;, FileMode.Create, FileAccess.Write, FileShare.None,<br /> 4096, false);<br />fs.Write(state.pixels, 0, numPixels);<br />fs.Close();<br />state.pixels = null;<br />fs = null;<br />lock (NumImagesMutex)<br /> {<br />NumImagesToFinish--;<br />if (NumImagesToFinish == 0)<br /> {<br />Monitor.Enter(WaitObject);<br />Monitor.Pulse(WaitObject);<br />Monitor.Exit(WaitObject);<br /> }<br /> }<br />}<br />using System;<br />using System.IO;<br />usingSystem.Threading;<br />usingSystem.Runtime.InteropServices;<br />usingSystem.Runtime.Remoting.Messaging;<br />usingSystem.Security.Permissions;<br />publicclassBulkImageProcAsync<br />{<br />publicconstStringImageBaseName = &quot;tmpImage-&quot;;<br />publicconstintnumImages = 200;<br />publicconstintnumPixels = 512 * 512;<br />publicstaticintprocessImageRepeats = 20;<br />publicstaticintNumImagesToFinish = numImages;<br />publicstaticObject[] NumImagesMutex = newObject[0];<br />publicstaticObject[] WaitObject = newObject[0];<br />publicclassImageStateObject<br /> {<br />publicbyte[] pixels;<br />publicintimageNum;<br />publicFileStreamfs;<br /> }<br />“Asynchronous File I/O”http://msdn.microsoft.com/en-us/library/kztecsys.aspx<br />State of Asynchronous I/O<br />
    19. 19. letProcessImageAsynci =<br />async { useinStream = File.OpenRead(sprintf&quot;Image%d.tmp&quot;i)<br />let! pixels = inStream.AsyncRead(numPixels)<br />let pixels&apos; = ProcessImage(pixels, i)<br />useoutStream = File.OpenWrite(sprintf&quot;Image%d.done&quot;i)<br />do!outStream.AsyncWrite(pixels&apos;) }<br />letProcessImagesAsync() =<br />let tasks = [ foriin 1..numImages -&gt;ProcessImageAsync(i) ]<br />letparallelTasks = Async.Parallel tasks<br />Async.RunSynchronouslyparallelTasks<br />Why Isn’t it This Easy?<br />
    20. 20. Read stream<br />asynchronously<br />letProcessImageAsynci =<br />async { useinStream = File.OpenRead(sprintf&quot;Image%d.tmp&quot;i)<br />let! pixels = inStream.AsyncRead(numPixels)<br />let pixels&apos; = ProcessImage(pixels, i)<br />useoutStream = File.OpenWrite(sprintf&quot;Image%d.done&quot;i)<br />do!outStream.AsyncWrite(pixels&apos;) }<br />letProcessImagesAsync() =<br />let tasks = [ for i in 1..numImages -&gt;ProcessImageAsynci ]<br />letparallelTasks = Async.Parallel tasks<br />Async.RunSynnchronouslyparallelTasks<br />This object coordinates<br />Write stream asynchronously<br />Generate the tasks and queue them in parallel<br />“!” <br />= “asynchronous”<br />Digging Deeper…<br />
    21. 21. letgetHtml (url:string) =<br />async { let request = WebRequest.Createurl<br />use! response = request.AsyncGetResponse()<br />use stream = response.GetResponseStream()<br />use reader = newStreamReader(stream)<br />return! reader.AsyncReadToEnd() }<br />What we’re really writing<br />letgetHtml (url:string) =<br />async.Delay(fun () -&gt;<br />let request = WebRequest.Createurl<br />async.Bind(request.AsyncGetResponse(), funresponse -&gt;<br />async.Using(response, fun response -&gt;<br />async.Using(response.GetResponseStream(), fun stream -&gt;<br />async.Using(new StreamReader(stream), fun reader -&gt;<br />reader.AsyncReadToEnd())))))<br />
    22. 22. How does it work?<br />Success Continuation<br />Async&lt;T&gt;<br />Execution Request<br />Exception Continuation<br />Cancellation Continuation<br />
    23. 23. Anatomy of an Async Operation<br />Async operations<br />Begin/End<br />typeSystem.Net.WebRequestwith<br />memberthis.AsyncGetRequestStream() =<br />Async.BuildPrimitive(<br />this.BeginGetRequestStream, <br />this.EndGetRequestStream)<br />
    24. 24. What Do We Get For Free?<br />Code that makes sense<br />Exception propagation<br />Cancellation checking<br />Simple resource lifetime management<br />
    25. 25. Twitter Example<br />
    26. 26. Parallel Programming<br />Task Parallel<br />Data Parallel<br />
    27. 27. Data Parallel ProgrammingPLINQ<br />Enable F# developers to leverage parallel hardware<br />Abstracts away parallelism details<br />Partitions and merges data intelligently<br />Works on any seq&lt;&apos;a&gt;/IEnumerable&lt;T&gt;<br />let q = ratings<br /> |&gt; PSeq.adapt<br /> |&gt; PSeq.filter(funp -&gt;p.Name = movieName &&<br />p.Rating &gt;= 3.0 &&<br />p.Rating &lt;= 5.0)<br /> |&gt; PSeq.sortBy(fun p -&gt;p.Rating)<br /> |&gt; PSeq.map(funp -&gt;p.CustomerId)<br />
    28. 28. Task Parallel Programming<br />Enable F# developers to create tasks in parallel<br />letcomputeHash path algorithm =<br />async { use stream = File.OpenRead path<br />let! bytes = stream.AsyncRead(intstream.Length)<br />let crypt = HashAlgorithm.Create algorithm<br />returncrypt.ComputeHash bytes }<br />let algorithms = [&quot;MD5&quot;;&quot;SHA1&quot;;&quot;SHA256&quot;;&quot;SHA384&quot;;&quot;SHA512&quot;]<br />let [|md5;sha1;sha256;sha384;sha512|] =<br />Async.RunSynchronously(<br />Async.Parallel<br /> [for algorithm in algorithms -&gt;<br />computeHash path algorithm])<br />
    29. 29. Task Parallel + Async Workflows<br />TPL Tasks integrated in .NET 4.0 Async Workflows<br />Integrate with pre-defined tasks<br />Calculate Futures<br />letgetStreamData (uri:string) =<br />async { let request = WebRequest.Createuri<br />use! response = request.AsyncGetResponse()<br />return [use stream = response.GetResponseStream()<br />use reader = new StreamReader(stream)<br />while not reader.EndOfStream<br />doyieldreader.ReadLine()] }<br />let result = Async.CreateAsTask &lt;| getStreamDatamyUri<br />do result.Start()<br />letresultValue = result.Value<br />
    30. 30. Bing Translator Example<br />
    31. 31. Actor Model Concurrency<br />Lots of little tasks<br />Each process does one task<br />Ant Colony<br />Ants are processes sending messages to each other<br />
    32. 32. Actor Model in Action…<br />let (&lt;--) (m:&apos;aMailboxProcessor) msg = m.Post(msg)<br />typePinger = Pong<br />typePonger = Ping ofMailboxProcessor&lt;Pinger&gt; | Stop<br />letponger = <br />newMailboxProcessor&lt;Ponger&gt;(funinbox -&gt;<br />let rec loop pongCount =<br />async { let! msg = inbox.Receive()<br />matchmsgwith<br /> | Ping outbox -&gt;<br /> outbox &lt;-- Pong<br />return! loop(pongCount + 1)<br /> | Stop -&gt; return () }<br /> loop 0)<br />
    33. 33. Actor Model in Action…<br />letpinger count pong =<br />  newMailboxProcessor&lt;Pinger&gt;(funinbox -&gt;<br />    let rec sendPing() = <br />      async { pong &lt;-- Ping(inbox)<br />              return! loop (count - 1) }<br />    and loop pingsLeft =<br />      async { let! msg = inbox.Receive()<br />              matchmsgwith<br />              | Pong -&gt;<br />                  ifpingsLeft &gt; 0 then<br />                    pong &lt;-- Ping(inbox)<br />                    return! loop(pingsLeft - 1)<br />                  else                    <br /> pong &lt;-- Stop<br />                    return () }<br />    sendPing())<br />
    34. 34. Web Crawling Example<br />
    35. 35. Ant Colony Example<br />
    36. 36. High Performance Computing<br />MPI.NET<br />Dryad/DryadLINQ<br />
    37. 37. What’s in Store for 2010?<br />
    38. 38. Ways to Learn F#<br />http://www.fsharp.net<br />F# Interactive (FSI)<br />Language Specification<br />F# Team Blogs<br />F# (FSharp) Discussion DL<br />http://cs.hubfs.net<br />CodePlex F# Samples<br />.NET Reflector<br />Go to Definition<br />
    39. 39. Books about F#<br />
    40. 40. Resources - Blogs<br />Don Symehttp://blogs.msdn.com/dsyme/<br />Luke Hobanhttp://blogs.msdn.com/lukeh/<br />Brian McNamarahttp://lorgonblog.spaces.live.com/<br />Chris Smithhttp://blogs.msdn.com/chrsmith/<br />Jomo Fisherhttp://blogs.msdn.com/jomo_fisher/<br />Planet F#http://feeds.feedburner.com/planet_fsharp<br />

    ×