Simon Peyton Jones (Microsoft Research) Tokyo Haskell Users Group April 2010.

Slides:



Advertisements
Similar presentations
Concurrency unlocked transactional memory for composable concurrency Tim Harris Maurice Herlihy Simon Marlow Simon Peyton Jones.
Advertisements

A Program Transformation For Faster Goal-Directed Search Akash Lal, Shaz Qadeer Microsoft Research.
Kathleen Fisher cs242 Reading: “A history of Haskell: Being lazy with class”,A history of Haskell: Being lazy with class Section 6.4 and Section 7 “Monads.
Ch. 7 Process Synchronization (1/2) I Background F Producer - Consumer process :  Compiler, Assembler, Loader, · · · · · · F Bounded buffer.
Kathleen Fisher cs242 Reading: “Beautiful Concurrency”,Beautiful Concurrency “The Transactional Memory / Garbage Collection Analogy”The Transactional Memory.
Concurrency The need for speed. Why concurrency? Moore’s law: 1. The number of components on a chip doubles about every 18 months 2. The speed of computation.
Software Transactional Memory Steve Severance – Alpha Heavy Industries.
Error Handling with Exceptions Concepts C and other earlier languages often had multiple error-handling schemes, and these were generally established.
1 Lecture 11 Interfaces and Exception Handling from Chapters 9 and 10.
Tim Harris Researcher Microsoft Corporation. Source: Table from
CS444/CS544 Operating Systems Introduction to Synchronization 2/07/2007 Prof. Searleman
CS444/CS544 Operating Systems Synchronization 2/16/2006 Prof. Searleman
Parallelism and Concurrency Koen Lindström Claessen Chalmers University Gothenburg, Sweden Ulf Norell.
1 Lecture 21: Transactional Memory Topics: consistency model recap, introduction to transactional memory.
1 Lecture 23: Transactional Memory Topics: consistency model recap, introduction to transactional memory.
Exceptions in Java Fawzi Emad Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
Exceptions and side-effects in atomic blocks Tim Harris.
Synchronization in Java Nelson Padua-Perez Bill Pugh Department of Computer Science University of Maryland, College Park.
Language Support for Lightweight transactions Tim Harris & Keir Fraser Presented by Narayanan Sundaram 04/28/2008.
1 New Architectures Need New Languages A triumph of optimism over experience! Ian Watson 3 rd July 2009.
Concurrency and Software Transactional Memories Satnam Singh, Microsoft Faculty Summit 2005.
Synchronization in Java Fawzi Emad Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
1 Sharing Objects – Ch. 3 Visibility What is the source of the issue? Volatile Dekker’s algorithm Publication and Escape Thread Confinement Immutability.
29-Jun-15 Java Concurrency. Definitions Parallel processes—two or more Threads are running simultaneously, on different cores (processors), in the same.
CPS110: Implementing threads/locks on a uni-processor Landon Cox.
1 CSCD 330 Network Programming Lecture 13 More Client-Server Programming Sometime in 2014 Reading: References at end of Lecture.
Comparative Programming Languages hussein suleman uct csc304s 2003.
And other languages…. must remember to check return value OR, must pass label/exception handler to every function Caller Function return status Caller.
David Walker Optional Reading: “Beautiful Concurrency”, “The Transactional Memory / Garbage Collection Analogy” “A Tutorial on Parallel and Concurrent.
Experience with Processes and Monitors in Mesa
Kathleen Fisher cs242 Reading: “Beautiful Concurrency”,Beautiful Concurrency “The Transactional Memory / Garbage Collection Analogy”The Transactional Memory.
Python Concurrency Threading, parallel and GIL adventures Chris McCafferty, SunGard Global Services.
CSE 230 Concurrency: STM Slides due to: Kathleen Fisher, Simon Peyton Jones, Satnam Singh, Don Stewart.
Java Threads 11 Threading and Concurrent Programming in Java Introduction and Definitions D.W. Denbo Introduction and Definitions D.W. Denbo.
Multithreading : synchronization. Avanced Programming 2004, Based on LYS Stefanus’s slides slide 4.2 Solving the Race Condition Problem A thread must.
Optimistic Design 1. Guarded Methods Do something based on the fact that one or more objects have particular states  Make a set of purchases assuming.
Haskell - A Perspective Presented by Gábor Lipták April 2011.
CSC321 Concurrent Programming: §5 Monitors 1 Section 5 Monitors.
ICS 313: Programming Language Theory Chapter 13: Concurrency.
DOUBLE INSTANCE LOCKING A concurrency pattern with Lock-Free read operations Pedro Ramalhete Andreia Correia November 2013.
QIAN XI COS597C 10/28/2010 Explicit Concurrent Programming in Haskell.
CS399 New Beginnings Jonathan Walpole. 2 Concurrent Programming & Synchronization Primitives.
13-1 Chapter 13 Concurrency Topics Introduction Introduction to Subprogram-Level Concurrency Semaphores Monitors Message Passing Java Threads C# Threads.
CS533 – Spring Jeanie M. Schwenk Experiences and Processes and Monitors with Mesa What is Mesa? “Mesa is a strongly typed, block structured programming.
COSC 3407: Operating Systems Lecture 9: Readers-Writers and Language Support for Synchronization.
Fall 2008Programming Development Techniques 1 Topic 20 Concurrency Section 3.4.
CGS 3763 Operating Systems Concepts Spring 2013 Dan C. Marinescu Office: HEC 304 Office hours: M-Wd 11: :30 AM.
1 Synchronization via Transactions. 2 Concurrency Quiz If two threads execute this program concurrently, how many different final values of X are there?
AtomCaml: First-class Atomicity via Rollback Michael F. Ringenburg and Dan Grossman University of Washington International Conference on Functional Programming.
MULTIVIE W Slide 1 (of 21) Software Transactional Memory Should Not Be Obstruction Free Paper: Robert Ennals Presenter: Emerson Murphy-Hill.
Optimistic Design CDP 1. Guarded Methods Do something based on the fact that one or more objects have particular states Make a set of purchases assuming.
Concurrency (Threads) Threads allow you to do tasks in parallel. In an unthreaded program, you code is executed procedurally from start to finish. In a.
Concurrency in Java MD. ANISUR RAHMAN. slide 2 Concurrency  Multiprogramming  Single processor runs several programs at the same time  Each program.
Atomic Tranactions. Sunmeet Sethi. Index  Meaning of Atomic transaction.  Transaction model Types of storage. Transaction primitives. Properties of.
R 1 Transactional abstractions: beyond atomic update Tim Harris r.
Parallelism and Concurrency Koen Lindström Claessen Chalmers University Gothenburg, Sweden Patrik Jansson.
Tutorial 2: Homework 1 and Project 1
Parallelism and Concurrency
(Nested) Open Memory Transactions in Haskell
Java Programming Language
Software Transactional Memory
Changing thread semantics
COP 4600 Operating Systems Fall 2010
Lecture 22: Consistency Models, TM
Java Concurrency 17-Jan-19.
Java Concurrency.
CSE 153 Design of Operating Systems Winter 19
CS333 Intro to Operating Systems
Java Concurrency.
Java Concurrency 29-May-19.
Presentation transcript:

Simon Peyton Jones (Microsoft Research) Tokyo Haskell Users Group April 2010

1yr5yr10yr15yr 1,000, ,000 The quick death Geeks Practitioners

1yr5yr10yr15yr 1,000, ,000 The slow death Geeks Practitioners

1yr5yr10yr15yr 1,000, ,000 The complete absence of death Geeks Practitioners Threshold of immortality

1yr5yr10yr 15yr 1,000, ,000 The committee language Geeks Practitioners

1,000, ,000 The second life? Geeks Practitioners “Learning Haskell is a great way of training yourself to think functionally so you are ready to take full advantage of C# 3.0 when it comes out” (blog Apr 2007) “I'm already looking at coding problems and my mental perspective is now shifting back and forth between purely OO and more FP styled solutions” (blog Mar 2007)

langpop.comlangpop.com Oct 2008

1976 packages 533 developers 256 new packages Jan-Mar uploads/day 4k downloads/day

Parallelism is a big opportunity for Haskell The language is naturally parallel (the opposite of Java) Everyone is worried about how to program parallel machines

 Explicit threads  Non-deterministic by design  Monadic: forkIO and STM  Semi-implicit  Deterministic  Pure: par and seq  Data parallel  Deterministic  Pure: parallel arrays  Shared memory initially; distributed memory eventually; possibly even GPUs  General attitude: using some of the parallel processors you already have, relatively easily main :: IO () = do { ch <- newChan ; forkIO (ioManager ch) ; forkIO(worker 1 ch)... etc... } f :: Int -> Int f x = a `par` b `seq` a + b where a = f (x-1) b = f (x-2)

 Explicit threads  Non-deterministic by design  Monadic: forkIO and STM  Semi-implicit  Deterministic  Pure: par and seq  Data parallel  Deterministic  Pure: parallel arrays  Shared memory initially; distributed memory eventually; possibly even GPUs  General attitude: using some of the parallel processors you already have, relatively easily main :: IO () = do { ch <- newChan ; forkIO (ioManager ch) ; forkIO(worker 1 ch)... etc... } f :: Int -> Int f x = a `par` b `seq` a + b where a = f (x-1) b = f (x-2) Today’s focus

Locks and condition variables After 30 years of research, the most widely-used co-ordination mechanism for shared-memory task-level concurrency is....

Locks and condition variables (invented 30 years ago) After 30 years of research, the most widely-used co-ordination mechanism for shared-memory task-level concurrency is....

16 A 10-second review:  Races: due to forgotten locks  Deadlock: locks acquired in “wrong” order.  Lost wakeups: forgotten notify to condition variable  Diabolical error recovery: need to restore invariants and release locks in exception handlers  These are serious problems. But even worse...

17 Scalable double-ended queue: one lock per cell No interference if ends “far enough” apart But watch out when the queue is 0, 1, or 2 elements long!

18 Coding style Difficulty of concurrent queue Sequential code Undergraduate

19 Coding style Difficulty of concurrent queue Sequential code Undergraduate Locks and condition variables Publishable result at international conference

20 Coding style Difficulty of concurrent queue Sequential code Undergraduate Locks and condition variables Publishable result at international conference Atomic blocks Undergraduate

21 atomic {... sequential get code... }  To a first approximation, just write the sequential code, and wrap atomic around it  All-or-nothing semantics: Atomic commit  Atomic block executes in Isolation  Cannot deadlock (there are no locks!)  Atomicity makes error recovery easy (e.g. exception thrown inside the get code) ACIDACID

One possibility:  Execute without taking any locks  Each read and write in is logged to a thread-local transaction log  Writes go to the log only, not to memory  At the end, the transaction tries to commit to memory  Commit may fail; then transaction is re-run Optimistic concurrency atomic { }

Realising STM in Haskell

Effects are explicit in the type system Effects are explicit in the type system –(reverse “yes”) :: String -- No effects –(putStr “no”) :: IO () -- Can have effects The main program is an effect-ful computation The main program is an effect-ful computation –main :: IO () main = do { putStr (reverse “yes”) ; putStr “no” }

Reads and writes are 100% explicit! You can’t say (r + 6), because r :: Ref Int main = do { r IO () incR r = do { v IO () incR r = do { v <- readRef r ; writeRef r (v+1) } newRef :: a -> IO (Ref a) readRef :: Ref a -> IO a writeRef :: Ref a -> a -> IO ()

main = do { r <- newRef 0 ; fork (incR r) ; incR r ;... } incR :: Ref Int -> IO () incR r = do { v IO () incR r = do { v <- readRef f; writeRef r (v+1) }  fork spawns a thread  it takes an action as its argument fork :: IO a -> IO ThreadId A race

 atomic is a function, not a syntactic construct  A worry: what stops you doing incR outside atomic? atomic :: IO a -> IO a main = do { r <- newRef 0 ; fork (atomic (incR r)) ; atomic (incR r) ;... }

 Better idea: atomic :: STM a -> IO a newTVar :: a -> STM (TVar a) readTVar :: TVar a -> STM a writeTVar :: TVar a -> a -> STM () incT :: TVar Int -> STM () incT r = do { v STM () incT r = do { v <- readTVar r; writeTVar r (v+1) } main = do { r <- atomic (newTVar 0) ; fork (atomic (incT r)) ; atomic (incT r) ;... }

 Notice that:  Can’t fiddle with TVars outside atomic block [good]  Can’t do IO inside atomic block [sad, but also good]  No changes to the compiler (whatsoever). Only runtime system and primops. ...and, best of all... atomic :: STM a -> IO a newTVar :: a -> STM (TVar a) readTVar :: TVar a -> STM a writeTVar :: TVar a -> a -> STM ()

 An STM computation is always executed atomically (e.g. incT2). The type tells you.  Simply glue STMs together arbitrarily; then wrap with atomic  No nested atomic. (What would it mean?) incT :: TVar Int -> STM () incT r = do { v STM () incT r = do { v <- readTVar r; writeTVar r (v+1) } incT2 :: TVar Int -> STM () incT2 r = do { incT r; incT r } foo :: IO () foo =...atomic (incT2 r)... Composition is THE way we build big programs that work

 STM monad supports exceptions:  In the call (atomic s), if s throws an exception, the transaction is aborted with no effect; and the exception is propagated into the IO monad  No need to restore invariants, or release locks!  See paper for the question of the exception value itself throw :: Exception -> STM a catch :: STM a -> (Exception -> STM a) -> STM a

Three new ideas retry orElse always

 retry means “abort the current transaction and re-execute it from the beginning”.  Implementation avoids the busy wait by using reads in the transaction log (i.e. acc) to wait simultaneously on all read variables withdraw :: TVar Int -> Int -> STM () withdraw acc n = do { bal Int -> STM () withdraw acc n = do { bal <- readTVar acc ; if bal < n then retry; ; writeTVar acc (bal-n) } retry :: STM ()

 No condition variables!  Retrying thread is woken up automatically when acc is written. No lost wake-ups!  No danger of forgetting to test everything again when woken up; the transaction runs again from the beginning. e.g. atomic (do { withdraw a1 3 ; withdraw a2 7 })

 Because retry can appear anywhere inside an atomic block, including nested deep within a call. e.g. atomic (do { withdraw a1 3 ; withdraw a2 7 })  Waits for a1>3 AND a2>7, without changing withdraw  Contrast: atomic (a1 > 3 && a2 > 7) {...stuff... } which breaks the abstraction inside “...stuff...”

atomic (do { withdraw a1 3 `orelse` withdraw a2 3 ;deposit b 3 }) Try this...and if it retries, try this...and and then do this orElse :: STM a -> STM a -> STM a

transfer :: TVar Int -> TVar Int -> TVar Int -> STM () transfer a1 a2 b = do { withdraw a1 3 `orElse` withdraw a2 3 ; deposit b 3 } atomic (transfer a1 a2 b `orElse` transfer a3 a4 b) transfer a3 a4 b)  transfer has an orElse, but calls to transfer can still be composed with orElse

 A transaction is a value of type (STM t)  Transactions are first-class values  Build a big transaction by composing little transactions: in sequence, using choice, inside procedures....  Finally seal up the transaction with atomic :: STM a -> IO a  No nested atomic! But orElse is like a nested transaction  No concurrency within a transaction!

Nice equations: –orElse is associative (but not commutative) –retry `orElse` s = s –s `orElse` retry = s (STM is an instance of MonadPlus)

 The route to sanity is by establishing invariants that are assumed on entry, and guaranteed on exit, by every atomic block  We want to check these guarantees. But we don’t want to test every invariant after every atomic block.  Hmm.... Only test when something read by the invariant has changed.... rather like retry

always :: STM Bool -> STM () newAccount :: STM (TVar Int) newAccount = do { v <- newTVar 0 ; always (do{ cts <- readTVar v ; return (cts >= 0) }) ; return v } An arbitrary boolean-valued STM computation Any transaction that modifies the account will check the invariant (no forgotten checks)

 always adds a new invariant to a global pool of invariants  Conceptually, every invariant is checked after every transaction  But the implementation checks only invariants that read TVars that have been written by the transaction ...and garbage collects invariants that are checking dead TVars always :: STM Bool -> STM ()

Everything so far is intuitive and arm- wavey Everything so far is intuitive and arm- wavey But what happens if it’s raining, and you are inside an orElse and you throw an exception that contains a value that mentions...? But what happens if it’s raining, and you are inside an orElse and you throw an exception that contains a value that mentions...? We need a precise specification! We need a precise specification!

No way to wait for complex conditions We have one

Conclusions  Atomic blocks (atomic, retry, orElse) are a real step forward  It’s like using a high-level language instead of assembly code: whole classes of low-level errors are eliminated.  Not a silver bullet: –you can still write buggy programs; –concurrent programs are still harder to write than sequential ones; –aimed at shared memory  But the improvement is very substantial