Your SlideShare is downloading. ×

Async and Parallel F#

4,093

Published on

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

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
4,093
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
0
Comments
0
Likes
10
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
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
  • Transcript

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

    ×