Software Transactional Memory - PowerPoint PPT Presentation

Software transactional memory l.jpg
Download
1 / 24

Software Transactional Memory. How D can make concurrent programming a piece of cake Bartosz Milewski D Programming Language. Obvious Things. Multi-Core is here to stay Programmers must use concurrency (Dead-) Lock Oriented Programming is BAD New paradigm badly needed. The Problem.

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

Download Presentation

Software Transactional Memory

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Software transactional memory l.jpg

Software Transactional Memory

How D can make concurrent programming a piece of cake

Bartosz Milewski

D Programming Language


Obvious things l.jpg

Obvious Things

  • Multi-Core is here to stay

  • Programmers must use concurrency

  • (Dead-) Lock Oriented Programming is BAD

  • New paradigm badly needed


The problem l.jpg

The Problem

void Toggle ()

{

if (x == 0)

x = 1;

else

x = 0;

}

  • Fetch value of x

  • Store it in a temporary

  • Compare with zero

  • Based on the result, write new value

What if, in the meanwhile, the original x was modified by another thread?

Write is based on incorrect assumption!


Logically speaking l.jpg

Logically Speaking

  • Theorem:

    • Hypothesis: x == 0 (read x, compare to 0)

    • Conclusion: x = 1 (write 1 into x)

  • Problem: Hypothesis invalidated before conclusion reached

  • Must re-check the hypothesis before writing!


Transaction l.jpg

Transaction

  • Delay checking: Log read values for later

  • Must re-check before writing: Log the “intent to write” (speculative writes) for later execution

  • Verify hypothesis : Are read values unchanged?

  • Reach conclusion: Execute writes from log to memory


What does it buy us l.jpg

What Does It Buy Us?

  • Concurrency issues postponed to the commit phase (read-check and write)

  • Commit uses generic code, which can be optimized and tested once for all

  • User code simple, less error-prone—code as if there were a single global lock

  • Increased concurrency—executes as if every word were separately locked

  • No deadlocks!


Stm in a nutshell l.jpg

STM in a Nutshell

  • Start a transaction: create log

  • Speculative execution—reads and writes logged

  • Commit phase (atomic)

    • Read-check

    • Write to memory

  • If failure, restart transaction


Composability l.jpg

Composability

  • Combining atomic operations using locks—almost impossible!

  • Atomic (transacted) withdrawalatomic { acc.Withdraw (sum); }

  • Atomic deposit—similar

  • Atomic transferatomic {accOne.Withdraw (sum);accTwo.Deposit (sum);}


Blocking transactions l.jpg

Blocking Transactions

  • Example: Producer/Consumer

atomic

{

Item * item = pcQueue.Get ();

}

Item * Get () atomic // PCQueue method

{

if (_queue.Count () == 0)

retry;

else

return _queue.pop_front ();

}


Retry l.jpg

Retry

  • Restart transaction without destroying the log

  • Make the read-log globally available

  • Block until any of the logged read locations changes

  • Every commit checks the read-sets of blocked transactions and unblocks the ones that overlap with its write-set


The beauty of retry l.jpg

The Beauty of Retry

  • Consumer doesn’t have to specify what it’s waiting for

  • Producer doesn’t have to signal anybody

  • Composability: Wait for two items

atomic

{

item1 = pcQueue.Get ();

item2 = pcQueue.Get ();

}


Object based stm l.jpg

Object-Based STM

  • Transactable (atomic) objects

    • Visible as opaque handles

    • Can be opened only inside transaction

    • Open (for read) returns a const pointer to the actual object

    • Open for write clones the object and returns pointer to the clone

atomic struct Foo { int x; }

atomic Foo f (new Foo); // an opaque handle

atomic { // start transaction

Foo * foo = f.open_write ();

++foo.x;

}


Cloning l.jpg

Cloning

  • Deep copy of the object

  • Embedded atomic handles are copied but not the objects they refer to

  • Transactable data structures build from small atomic objects (tree from nodes)

  • Value-semantic objects (e.g. structs) cloned by copy construction


Type system support l.jpg

Type System Support

  • Struct or class marked as “atomic”—all methods (except constructor) “atomic”

  • Open and open_write can be called only inside a transaction—i.e. from inside:

    • Atomic block

    • Atomic function/method

  • Atomic function/method may only be called from inside a transaction


Singly linked list l.jpg

Singly-Linked List

struct Slist // not atomic

{

this () {

// Insert sentinels

SNode * last = new SNode (Infin, null);

_head = new SNode (MinusInfin, last);

}

// atomic methods

const (SNode) * Head () const atomic

{

retrun _head.open ();

}

void Insert (int i) atomic;

void Remove (int i) atomic;

private:

atomic SNode _head; // atomic handle

}


Slide16 l.jpg

Node

struct SNode atomic

{

public:

this (int i, const (SNode) * next) {

_val = i; _next = next;

}

// atomic methods (by default)

int Value () const { return _val; }

const (SNode) * Next () const {

return _next.open ();

}

Snode * SetNext (const (SNode) * next) {

SNode * self = this.open_write ()

self._next = next;

return self;

}

private:

int_val;

atomic Snode_next;

}


Insert l.jpg

Insert

atomic { myList.Insert (x); } // transactioned

void Insert (int i) atomic

{

const (SNode) * prev = Head (); // sentinel

const (SNode) * cur = prev.Next ();

while (cur._val < i)

{

prev = cur;

cur = prev.Next ();

}

assert (cur != 0); // at worst high sentinel

SNode * newNode = new SNode (i, cur);

(void) prev.SetNext (newNode);

}


Implementation l.jpg

Implementation

  • Versioning and Locking

    • Global Version Clock (always even)

    • Version numbers always increase

    • (Hidden) version/lock word per atomic object (lock is the lowest bit)

  • Consistent Snapshot maintenance

    • Version checks when opening an object

    • Read-check during commit


Consistent snapshot l.jpg

Consistent Snapshot

  • Transaction starts by reading Version Clock into the transaction’s read-version variable

  • Open object

    • Check the object lock (bit). If taken, abort

    • Check object version number. If it’s greater than read-version abort


Logging l.jpg

Logging

  • Every open is recorded in read-log

    • Pointer to original object (from which its version lock can be retrieved)

  • Every open_write is recorded in read-log and write_log

    • Pointer to original object

    • Pointer to clone

  • Okay to call open_write after open (read)


Commit l.jpg

Commit

  • Lock all objects recorded in the write-log

    • Bounded spinlock on each version lock

  • Increment global Version Clock—store as transaction’s write-version

  • Sequence Point (if transaction commits, that’s when it “happened”)

  • Read-check

    • Re-check object version numbers against read-version


Commit writes l.jpg

Commit Writes

  • For each location in the write-log

    • Swap the clone in place of original

    • Stamp it with write-version

    • Unlock


D work l.jpg

D Work

  • We have C implementation (Brad Roberts’ port of GPL’d Dice, Shalev, and Shalit)

  • Write D implementation

  • Modify type system


Bibliography l.jpg

Bibliography

  • Dave Dice, Ori Shalev, and Nir Shavit. Transactional Locking II

  • Tim Harris, Simon Marlow, Simon Peyton Jones, and Maurice Herlihy. Composable Memory Transactions. ACM Conference on Principles and Practice of Parallel Programming 2005 (PPoPP'05). 2005.


  • Login