STM in Haskell

42
Some Recent Advances in Haskell Siddharth Agarwal (Y7429) Advisor: Dr. A. Karkare

description

 

Transcript of STM in Haskell

Page 1: STM in Haskell

Some Recent Advances in Haskell

Siddharth Agarwal (Y7429)Advisor: Dr. A. Karkare

Page 2: STM in Haskell

CS497

• Software transactional memory• Nested data parallelism• CUDA and Haskell

Page 3: STM in Haskell

CS497

• Software transactional memory• Nested data parallelism• CUDA and Haskell

Page 4: STM in Haskell

The world is multi-core

Page 5: STM in Haskell

Lock-based synchronization

• Protect shared mutable state• acquire lockdo stuffrelease lock

• More complex mechanisms (semaphores, monitors) can be built on top

• Familiar to programmers• Difficult to use

Page 6: STM in Haskell

Deadlocks

Two processes each hold a lock that the other one wants

Process 1Process 1 Process 2Process 2

AA BB

Page 7: STM in Haskell

Priority inversion

A low-priority process holds a lock that a high-priority process needs

Low prio processLow prio process High prio processHigh prio process

LockLock

Page 8: STM in Haskell

Non-composable

• Classic example: Bank account• API: two synchronized methods: credit(amount) and debit(amount)

• As long as you’re just depositing or withdrawing money, you’re fine

Page 9: STM in Haskell

But what if…

• you want to transfer money from one account to another?

• account1.debit(x); account2.credit(x); causes the money to “vanish” in between

• In general, compose synchronized operations into a larger synchronized operation

Page 10: STM in Haskell

Solution 1

• Add a transfer() method to the API• Requires forethought by the API designer • 3-way, 4-way, … n-way transfers?

Page 11: STM in Haskell

Solution 2

• Expose the locks• Need to trust calling code to use the locks

properly• Shifts the problem one level up

Page 12: STM in Haskell

Solution 3

• Add a wrapper API with its own locking• How do you make others use your wrapper?

Page 13: STM in Haskell

Locks aren’t composable

• In general, it is not possible to combine two lock-based synchronized operations into a larger synchronized one

• The solutions are hacks around this basic flaw

Page 14: STM in Haskell

And all we wanted to do was…

Atomically account1.debit(x); account2.credit(x);

Page 15: STM in Haskell

And all we wanted to do was…

atomic { account1.debit(x); account2.credit(x);}

Page 16: STM in Haskell

What if…

• We could declare sections as atomic• Retriesatomic { if (items < 0) retry; …}

Page 17: STM in Haskell

Can we do this with locks?

• Limited success• Why not borrow another concept from

databases?

Page 18: STM in Haskell

Transactions

• Ordered sets of operations• All-or-nothing• In databases, ACID semantics

Page 19: STM in Haskell

Transactional memory

• The C and D aren’t relevant, so let’s drop them

• Atomicity and isolation• Software TM first proposed by Shavit and

Touitou (PODC’95)• Language support (Java) first looked at by

Harris and Fraser (OOPSLA’03)

Page 20: STM in Haskell

Software transactional memory

Maintain a transaction log

TLog Old New

x 200 200

y 100 150

Memory Value Version

x 200 42

y 100 14

z 300 27

Page 21: STM in Haskell

Software transactional memory

On read, read from or add to the logx = z - 50;

TLog Old New

x 200 200

y 100 150

Memory Value Version

x 200 42

y 100 14

z 300 27z 300 300

Page 22: STM in Haskell

Software transactional memory

On write, write to the logx = z - 50;

TLog Old New

x 200 200

y 100 150

z 300 300

Memory Value Version

x 200 42

y 100 14

z 300 27

TLog Old New

x 200 250

y 100 150

z 300 300

Page 23: STM in Haskell

Software transactional memory

On commit, (a) check and record version for unmodified data

TLog Old New

x 200 250

y 100 150

z 300 300

Memory Value Version

x 200 42

y 100 14

z 300 27

TLog Old New

x 200 250

y 100 150

z 300, 27 300

Page 24: STM in Haskell

TLog Old New

x 200 250

y 100 150

z 300, 27 300

Software transactional memory

(b) Lock locations to be modified

Memory Value Version

x 200 42

y 100 14

z 300 27

Memory Value Version

x 200 42

y 100 14

z 300 27

Page 25: STM in Haskell

Memory Value Version

x 200 42

y 100 14

z 300 27

TLog Old New

x 200 250

y 100 150

z 300, 27 300

Software transactional memory

(c) Check version numbers, then write new values back

Memory Value Version

x 250 42

y 150 14

z 300 27

Page 26: STM in Haskell

Memory Value Version

x 250 42

y 150 14

z 300 27

Memory Value Version

x 250 43

y 150 15

z 300 27

TLog Old New

x 200 250

y 100 150

z 300, 27 300

Software transactional memory

(d) Increment version numbers and unlock

Hardware support needed: just CAS

Page 27: STM in Haskell

Problem 1: Overhead

• Does each location need a version number?• Solutions– Hashing– Tag locations as TM

Page 28: STM in Haskell

Problem 2: I/O

• atomic { launchMissiles(); if (*) retry;}

• Perform on commit– What if you need input?

• OnCommit/OnRollback operations• Forbid I/O– Dynamically or statically?

Page 29: STM in Haskell

Problem 3: Weak or strong atomicity?

• Same memory location accessed both inside and outside an atomic block

• Forbid this, making the question moot?• STM.NET chose weak atomicity and in-place

updates, which led to major problems

Page 30: STM in Haskell

Haskell

• Strictly typed, lazy, pure functional language

Page 31: STM in Haskell

Haskell

• Strictly typed, lazy, pure functional language• Pure: Functions with side-effects must be

“marked”• Marking done through the type system

Page 32: STM in Haskell

I/O in Haskell

int f(int x) { return (x + 2);}

f x = x + 2f :: Integer -> Integer

Page 33: STM in Haskell

I/O in Haskellint g(int x) { System.out.println(“Hello, world!”); return (x + 2);}

g x = do { putStrLn “Hello, world!”; return (x + 2);}g :: Integer -> IO Integer

Page 34: STM in Haskell

I/O in Haskellint g(int x) { System.out.println(“Hello, world!”); return (x + 2);}

g x = do putStrLn “Hello, world!” return (x + 2)

g :: Integer -> IO Integer

Page 35: STM in Haskell

I/O in Haskell

• Functions with side-effects are marked at compile time

• Compiler can perform checks (e.g. forbidding I/O)

• STM is just another kind of I/O

Page 36: STM in Haskell

STM in Haskell

• A different marker: STM• Transactional memory needs to be declared

explicitly as TVar• Most memory is not transactional– Most memory is not mutable!– Prevents problem 1 (overhead)

Page 37: STM in Haskell

STM in Haskell

• I/O forbidden inside STM– Prevents problem 2 (I/O)– STM to IO converter called atomically

• Accesses to STM variables are through readTVar and writeTVar– They can only be called inside STM blocks– Prevents problem 3 (atomicity)

Page 38: STM in Haskell

STM in Haskell is composable

• Two types of composability:– Sequential– Alternative-based

Page 39: STM in Haskell

Alternative-based composition

• Provide two or more alternatives• If the first alternative retries, try the next one• Exposed through the orElse operator

Page 40: STM in Haskell

Putting it all together

(Demo)

Page 41: STM in Haskell

Future directions

• Transactional memory-only operations are a solved problem in Haskell

• Hook into other transaction providers– Databases– File system

Page 42: STM in Haskell

Thank you