360 likes | 605 Views
Software Transactional Memory for Dynamic-Sized Data Structures (DSTM – Dynamic STM). Maurice Herlihy, Victor Luchangco, Mark Moir, William N. Scherer III. PODC 2003. Presentation prepared by Adi Suissa for TM seminar, fall 2008/9. Overview. Short recap and DSTM contributions
E N D
Software Transactional Memory for Dynamic-Sized Data Structures(DSTM – Dynamic STM) Maurice Herlihy, Victor Luchangco, Mark Moir, William N. Scherer III PODC 2003 Presentation prepared by Adi Suissa for TM seminar, fall 2008/9
Overview • Short recap and DSTM contributions • How to use DSTM? • Example • Diving into DSTM • Example 2 • Improving performance
The computation model Starting transaction Read-Transactional(o1) Write-Transactional(o2) Read(o3) Write(o4) Commit-Transaction
The computation model • Committing a transaction can have two outcomes: • Success: the transaction’s operations take effect • Failure: the operations are discarded • Library Implemented in Java and in C++
Comparison with the Shavit-Toutitou TM • Only static memory – need to declare the memory that can be transactioned statically • We want the ability to create transactional objects dynamically • Only static transactions – transactions need to declare which addresses they are going to access before the transaction begins • We want to let transactions determine which object to access based on information of objects read inside a transaction • Obstruction-free (rather than non-blocking)
Overview • Short recap and what’s new? • How to use DSTM? • Example • Diving into DSTM • Example 2 • Improving performance
Threads • A thread that executes transactions must inherit from TMThread • Each thread can run a single transaction at a time class TMThread : Thread { void beginTransaction(); boolcommitTransaction(); void abortTransaction(); }
Objects (1) • All TM objects must implement the TMCloneable interface: • This method clones the object, but programmers don’t need to handle synchronization issues intefaceTMCloneable { Object clone(); }
Objects (2) • In order to make an object transactional, need to wrap it • TMObject is a container for regular Java objects TMObject Object
Opening an object • Before using a TMObject in a transaction, it must be opened • An object can either be opened for READ or WRITE (and read) class TMObject { TMObject(Object obj); enum Mode {READ, WRITE}; Object open(Mode mode); }
Overview • Short recap and what’s new? • How to use DSTM? • Example • Diving into DSTM • Example 2 • Improving performance
An atomic counter (1) • The counter has a single data member and two operations: • The object is shared among some threads class Counter : TMCloneable { intcounterValue = 0; void inc(); // increment the value int value(); // returns the value Object clone(); }
An atomic counter (2) • When a thread wants to access the counter in a transaction, it must first open the object using the encapsulated version: Counter counter = new Counter(); TMObjecttranCounter = new TMObject(counter); ((TMThread)Thread.currentThread).beginTransaction(); … Counter counter = (Counter)tranCounter.open(WRITE); counter.inc(); … ((TMThread)Thread.currentThread).commitTransaction(); Returns true/false to indicate commit status
Overview • Short recap and what’s new? • How to use DSTM? • Example • Diving into DSTM • Example 2 • Improving performance
DSTM implementation • Transactional object structure: status transaction new object start Data old object TMObject Locator Data
Current object version • The current object version is determined by the status of the transaction that most recently opened the object in WRITE mode: • committed: the new object is the current • aborted: the old object is the current • active: the old object is the current, and the new is tentative • The actual version only changes when the commit succeeds
Opening an object (1) • Lets assume transaction A opens object o in WRITE mode. • Let transaction B be the transaction that most recently opened o in WRITE mode. • We need to distinguish between the following cases: • B is committed • B is aborted • B is active
Opening an object (2) – B committed committed transaction Data new object start old object If CAS fails, restarts from the beginning o Data B’s Locator clone 4 Use CAS in order to replace locator active transaction new object Data old object A’s Locator 3 1 A sets old object to the previous new A creates a new Locator 2 A clones the previous new object, and sets new
Opening an object (3) – B aborted aborted transaction Data new object start old object o Data B’s Locator 4 Use CAS in order to replace locator active transaction clone new object Data old object A’s Locator 1 3 A sets old object to the previous old A creates a new Locator 2 A clones the previous old object, and sets new
Opening an object (4) – B active • Problem: B is active and can either commit or abort, so which version (old/new) should we use? • Answer: A and B are conflicting transactions, that run at the same time • Use Contention Manager to decide which should continue and which should abort • If B needs to abort, try to change its status to aborted (using CAS)
Opening an object (5) • Lets assume transaction A opens object o in READ mode • Fetch the current version just as before • Add the pair (o, v) to the readers list (read-only table)
Committing a transaction • The commit needs to do the following: • Validate the transaction • Change the transaction’s status from active to committed (using CAS)
Validating transactions • What? • Validate the objects read by the transaction • Why? • To make sure that the transaction observes a consistent state • How? • For each pair (o, v) in the read-only table, verify that v is still the most recently committed version of o • Check that (status == active) If the validation fails, throw an exception so the user will restart the transaction from the beginning
Validation inconsistency • Assume two threads A and B • If B after A, then o1 = 2, o2 = 1; • If A after B, then o1 = 1, o2 = 2 • If they run concurrently we can have o1 = 1, o2 = 1 which is illegal Thread A 1. x <- read(o1) 2. w(o2, x + 1) Thread B 1. y <- read(o2) 2. w(o1, y + 1) Initially: o1 = 0 o2 = 0
Conflicts • Conflicts are detected when: • A transaction first opens an object and finds that it is open for modification by another transaction • When the transaction validates its read set (on opening an object or commit)
Overview • Short recap and what’s new? • How to use DSTM? • Example • Diving into DSTM • Example 2 • Improving performance
Ordered Integer List – IntSet (1) Min 3 4 8 Max 6
Ordered Integer List – IntSet (2) class List implements TMCloneable { int value; TMObject next; List(int v) { value = v; } public Object clone() { List newList = new List(value); newList.next = next; return newList; } } Should have been called Element
Ordered Integer List – IntSet (3) class IntSet { TMObject first; // the list’s anchor IntSet() { List firstList = new List (Integer.MIN_VALUE); first = new TMObject(firstList); firstList.next = new TMObject( new List(Integer.MAX_VALUE)); } }
Ordered Integer List – IntSet (4) class IntSet { boolean insert(int v) { List newList = new List(v); TMObjectnewNode = new TMObject(newList); TMThread thread = Thread.currentThread(); while (true) { thread.beginTransaction(); boolean result = true; try { … } catch (Denied d) {} if (thread.commitTransaction()) return result; } } }
Ordered Integer List – IntSet (5) try { List prevList = (List)this.first.open(WRITE); List currList = (List)prevList.next.open(WRITE); while (currList.value < v) { prevList = currList; currList = (List)currList.next.open(WRITE); } if (currList.value == v) { result = false; } else { result = true; newList.next = prevList.next; prevList.next = newNode; } }
Overview • Short recap and what’s new? • How to use DSTM? • Example • Diving into DSTM • Example 2 • Improving performance
Single entrance • What is the problem with the previous example? • How can it be solved? • Opening for READ on traversal • Maybe something more sophisticated?
Releasing an object • An object that was open for READ can be released • What does it imply? • Careful planning • Can increase performance • What happens if we open an object, release it and open it again in the same transaction? • Can lead to validation problems