46
Software Transactional Memory Yoav Cohen Seminar in Distributed Computing Spring 2007

Software Transactional Memory

  • Upload
    abiba

  • View
    26

  • Download
    2

Embed Size (px)

DESCRIPTION

Software Transactional Memory. Yoav Cohen Seminar in Distributed Computing Spring 2007. Agenda. Motivation behind STM Intro to STM Static STM Implemented by Shavit and Touitou Dynamic STM Implemented by Herlihy et al. Motivation. Material covered so far: Mutual Exclusion (Netanel) - PowerPoint PPT Presentation

Citation preview

Page 1: Software Transactional Memory

Software Transactional Memory

Yoav CohenSeminar in Distributed Computing

Spring 2007

Page 2: Software Transactional Memory

Agenda

Motivation behind STM Intro to STM Static STM Implemented by Shavit and

Touitou Dynamic STM Implemented by Herlihy et

al.

Page 3: Software Transactional Memory

Motivation

Material covered so far: Mutual Exclusion (Netanel) Specifications for concurrent objects (Liza) Registers for concurrent access (Yaniv) Replace locks with HTM (Royi and Merav)

What else do we need?!

Page 4: Software Transactional Memory

HTM Shortcomings

Blocking - Can still deadlock A thread is killed without releasing a lock A thread is interrupted with a Page Fault while holding

the lock

It’s hardware Suggested at 1993 (Herlihy and Moss) - Not yet

implemented

Page 5: Software Transactional Memory

STM 101

Same ideas as HTM A thread executes a transaction The transaction either commits or aborts

Different from HTM Non-blocking - The system makes progress Implemented in software - Available today

Page 6: Software Transactional Memory

STM 101

A thread wants to change a shared object1) The thread announces it2) The thread copies the object to its private

memory3) The thread changes its private copy4) The thread updates the changes

Page 7: Software Transactional Memory

STM 101

Two ways to update an object Selective update - Update selected locations

Local copy

Original object

Page 8: Software Transactional Memory

STM 101

Two ways to update an object Replacing the object all together

Local copy

Original object

Original object

Page 9: Software Transactional Memory

Software Transactional Memory Nir Shavit, Dan Touitou (1995)

A non-blocking concurrency framework implemented in software

Uses the selective update approach

Page 10: Software Transactional Memory

Overview

Thread 1

Thread 2

Page 11: Software Transactional Memory

The System Model

We assume that every shared memory location supports these 4 operations: Writei(L,v) - thread i writes v to L Readi(L,v) - thread i reads v from L LLi(L,v) - thread i reads v from L and marks

that L was read by I SCi(L,v) - thread i writes v to L and returns

success if L is marked as read by i. Otherwise it returns failure.

Page 12: Software Transactional Memory

Threadclass Rec {

boolean stable = false;boolean,int status= (false,0); //can have two values…boolean allWritten = false;int version = 0;int size = 0;int locs[] = {null};int oldValues[] = {null};

}

Each thread is defined by an instance of a Rec class(short for record).

The Rec instance definesthe current transaction thethread is executing (only one transaction at a time)

Page 13: Software Transactional Memory

The STM Object

Memory

Ownerships

statusversionsizelocs[]oldValues[]

Rec1

statusversionsizelocs[]oldValues[]

Rec2

statusversionsizelocs[]oldValues[]

Recn

This is the shared memory

Pointers to threads

Page 14: Software Transactional Memory

Flow of a transaction

startTransaction Thread i

initialize

transaction

acquireOwnershipsagreeOldValues

calcNewValues

updateMemory

releaseOwnerships

releaseOwnerships

isInitiator?

ThreadsSTM

(Failure,failed loc)

FT

Initiatehelping

transactionto failed loc

(isInitiator:=F)

(Null, 0)

Success

Failure

Page 15: Software Transactional Memory

The STM Objectpublic class STM {

int memory[];Rec ownerships[];

public boolean, int[] startTranscation(Rec rec, int[] dataSet){...};

private void initialize(Rec rec, int[] dataSet)private void transaction(Rec rec, int version, boolean isInitiator) {...};private void acquireOwnerships(Rec rec, int version) {...};private void releaseOwnershipd(Rec rec, int version) {...};private void agreeOldValues(Rec rec, int version) {...};private void updateMemory(Rec rec, int version, int[] newvalues) {...};

}

Page 16: Software Transactional Memory

Implementationpublic boolean, int[] startTranscation(Rec rec, int[] dataSet) {

initialize(rec, dataSet);rec.stable = true;transaction(rec, rec.version, true);rec.stable = false;rec.version++;if (rec.status) return (true, rec.oldValues);else return false;

}

This notifies other threads that I can be helped

rec – The thread that executes this transaction.dataSet – The location in memory it needs to own.

Page 17: Software Transactional Memory

Implementationprivate void transaction(Rec rec, int version, boolean isInitiator) {

acquireOwnerships(rec, version); // try to own locations

(status, failedLoc) = LL(rec.status); if (status == null) { // success in acquireOwnerships

if (versoin != rec.version) return;SC(rec.status, (true,0));

}

(status, failedLoc) = LL(rec.status);if (status == true) { // execute the transaction

agreeOldValues(rec, version);int[] newVals = calcNewVals(rec.oldvalues); updateMemory(rec, version);releaseOwnerships(rec, version);

}else { // failed in acquireOwnerships

releaseOwnerships(rec, version);if (isInitiator) {

Rec failedTrans = ownerships[failedLoc];if (failedTrans == null) return;else { // execute the transaction that owns the location you want

int failedVer = failedTrans.version;if (failedTrans.stable) transaction(failedTrans, failedVer, false);

}}

}}

rec – The thread that executes this transaction.version – Serial number of the transaction.isInitiator – Am I the initiating thread or the helper?

Another thread own the locations I need and it hasn’t finished its transaction yet.

So I go out and execute its transaction in order to help it.

Page 18: Software Transactional Memory

Implementationprivate void acquireOwnerships(Rec rec, int version) {

for (int j=1; j<=rec.size; j++) {while (true) do {

int loc = locs[j];if LL(rec.status) != null return; // transaction completed by some other threadRec owner = LL(ownerships[loc]); if (rec.version != version) return; if (owner == rec) break; // location is already mineif (owner == null) { // acquire location

if ( SC(rec.status, (null, 0)) ) { if ( SC(ownerships[loc], rec) ) { break; }}

}else {// location is taken by someone else

if ( SC(rec.status, (false, j)) ) return;}

}

}}

If I’m not the last one to read this field, it means that another thread is trying to execute this transaction. Try to loop until I succeed or until the other thread completes the transaction

Page 19: Software Transactional Memory

Implementationprivate void agreeOldValues(Rec rec, int version) {

for (int j=1; j<=rec.size; j++) {int loc = locs[j];if ( LL(rec.oldvalues[loc]) != null ) {

if (rec.version != version) return;SC(rec.oldvalues[loc], memory[loc]);

}}

}

private void updateMemory(Rec rec, int version, int[] newvalues) {for (int j=1; j<=rec.size; j++) {

int loc = locs[j];int oldValue = LL(memory[loc]);if (rec.allWritten) return; // work is doneif (rec.version != version) return;if (oldValue != newValues[j]) SC(memory[loc], newValues[j]);

}if (! LL(rec.allWritten) ) {

if (rec.version != version) SC(rec.allWritten, true);}

}

Copy the dataSet to my private space

Selectively update the shared memory

Page 20: Software Transactional Memory

Proving the Non-blocking Property

Every failing transaction has a thread which writes Failure to its status field.

Intuition – Let’s show that a situation where the system is stuck can’t happen.

Proof outline – Assume the system is stuck and derive a contradiction.

Page 21: Software Transactional Memory

Proving the Non-blocking Property

Claim (No proof): Given a failing transaction, in which the failing thread failed to acquire a location A, all threads executing it will never acquire ownership of a location which is higher than the A.

Page 22: Software Transactional Memory

Proving the Non-blocking Property

The system is stuck – There are infinitely many transactions that do not succeed.1) Number of failing transactions is finite – The

other ones are stuck in a loop2) Number of failing transactions is infinite

Page 23: Software Transactional Memory

Proving the Non-blocking Property

Number of failing transactions is finite Other ones are stuck in the loop in

acquireOwnerships. This can only happen if some threads are

trying to acquire the same location for the same transaction.

This state can’t be reached (on the board). A contradiction.

T1 (Loop)T2 (Fail)T3 (Loop)……Tn (Loop)

Page 24: Software Transactional Memory

Proving the Non-blocking Property

Number of failing transactions is infinite Since the number of locations is finite, there exists

at least one location which is a failing location infinitely often.

Choose A, the highest of those locations. Intuition – If A is a failing location infinitely often,

there are infinitely many transactions who acquired A and failed.

Contradiction – A is not the highest location.

Page 25: Software Transactional Memory

Limitations of STM

Static - Information about transactions is required beforehand: Size DataSet

A static software transactional memory is limited only to predefined transactions and data structures.

Page 26: Software Transactional Memory

Performance of STM

In stable scenarios, it has a lower throughput than locks.

But, it is non-blocking, hence the system will always progress.

Page 27: Software Transactional Memory

Dynamic STMHerlihy, Moir, Luchangco, Scherer (2003)

Suited for Dynamic-Sized Data Structures

Uses the pointers swap technique

Introduces a weaker non-blocking property called obstruction freedom

Introduces Contention Managers

Page 28: Software Transactional Memory

Thread

A thread announces the start of a transaction A thread executes a series of operations on shared

objects A thread tries to commit the transaction

public class TMThread {public void beginTransaction();public void abortTransaction();public boolean commitTransaction();

}

Page 29: Software Transactional Memory

Flow of a transaction

TMThread i

ThreadsConcurrent Dynamic-Sized Data Structure

SharedObject

someMethod()

Thread.startTransaction()

SharedObject.open(WRITE)

SharedObject.release()

Thread.commitTransaction()

end someMethod()

Committing a transaction is done atomically!

Page 30: Software Transactional Memory

A concurrent systemView from above

TMThread j

Threads

TMThread k

TMThread i

TMThread m

Page 31: Software Transactional Memory

Opening a shared object

Intuition: When you open a shared object you get a

clone. You change the clone When you commit the transaction the

clone replaces the original object

Page 32: Software Transactional Memory

Structure of a shared object

Locator

transactionoldObjectnewObject

Data Data

TMObject

ACTIVE

Transaction

Page 33: Software Transactional Memory

Implementationclass Transaction {

enum Status {ACTIVE, COMMITTED, ABORTED};

Status status = Status.ACTIVE; }

Initialized to ACTIVE

Page 34: Software Transactional Memory

Implementationclass TMObject {

// internal classesenum AccessType {WRITE, READ};class Locator {

Transaction transaction;Object newObject;Object oldObject;

}

// data membersLocator locator;

// methodspublic void open(AccessType type) throws DeniedException {};

}

Ways to access the object

Pointers to the object’s data

Access the object

Page 35: Software Transactional Memory

Opening a shared object for Writing

public Object open(AccessType type) throws DeniedException {if (type==AccessType.WRITE) {

Locator newLocator = new Locator();newLocator.transaction = TMThread.getCurrentTransaction();if (locator.transaction.status==Status.ACTIVE) {

resolveConflict();}else {

if (locator.transaction.status==Status.COMMITTED) {newLocator.oldObject = locator.newObject;newLocator.newObject = locator.newObject.clone();

}else if (locator.transaction.status==Status.ABORTED) {

newLocator.oldObject = locator.oldObject;newLocator.newObject = locator.oldObject.clone();

}validateTransaction(newLocator.transaction)return newLocator.newObject;

}}

}

Trying to access an already open object

Make sure thetransaction is

stillactive and its

readtable is up to

date

Page 36: Software Transactional Memory

Opening a shared object for Writing

COMMITTED

locator

transactionoldObjectnewObject

Data DatanewLocator

transactionoldObjectnewObject

Data

clone()

ACTIVE

Because the last transaction

committed we take its changes

Page 37: Software Transactional Memory

Opening a shared object for Writing

ABORTED

locator

transactionoldObjectnewObject

Data DatanewLocator

transactionoldObjectnewObject

Dataclone()

ACTIVEBecause the last

transactionaborted we discard itschanges

Page 38: Software Transactional Memory

Opening a shared object for Reading

Intuition: Just have to make sure threads read the most updated version

Practice: We keep a Thread Local table of the objects we opened for

read and their latest version We keep a counter for each object to track number of open

and release invocations We increment the counter when open is called We decrement the counter when release is called. If

counter == 0 we remove the object from the table

Page 39: Software Transactional Memory

Opening a shared object for Reading

class ReadTable {class ReadTableItem {

Object object;int counter;

}Map<Integer, ReadTableItem> readTable;

void insert(int objID, Object objInst) {if ( readTable.containsKey(objID) ) {

ReadTableItem item = readTable.get(objID);item.counter++;

}else {

ReadTableItem newItem = new ReadTableItem(objInst,1);readTable.put(objID, newItem);

}}

void remove(int objID) {...}

}

The object and its counter

This is how we open an object for reading.

Page 40: Software Transactional Memory

Opening a shared object for Reading

public class TMThread {ThreadLocal<ReadTable> readTable;

public void beginTransaction();public void abortTransaction();public boolean commitTransaction();

}

Each thread has a read table

Page 41: Software Transactional Memory

Committing a transaction

Commiting a transaction requires 2 steps:1. Validating the read table of the thread2. Using Compare&Swap to change the

transaction status from ACTIVE to COMMITED

Page 42: Software Transactional Memory

Examplepublic class SomeDynamicSizedDataStructure {

TMObject data;

public boolean insert(Element elem) {TMThread thread = (TMThread) Thread.getCurrentThread();while (true) { // loop until commited or aborted

thread.beginTransaction();boolean result;try {

data.open(WRITE);/* Insert elem to data here */data.release();result = true;

} catch (DeniedException e) {/* Could not open a shared object */result = fasle;

}if (thread.commitTransaction() == true) return result;

}}

}

Page 43: Software Transactional Memory

Non-blocking

The DSTM implementation ensures a non-blocking property called obstruction-freedom.

It means that any thread that runs alone for a long enough time makes progress.

Weaker than lockout-freedom of STM

Page 44: Software Transactional Memory

Contention Management

Contention Management policy - What does a thread do when it encounters a conflict?

The DSTM implementation has an extension mechanism to allow for different contention management policies.

These extensions are called Contention Managers.

Page 45: Software Transactional Memory

Contention Managers

Each thread has a reference to a Contention Manager.

Whenever the thread encounters a conflict, it advices with its Contention Manger to decide what to do.

When a conflict is encountered a thread can either abort itself, wait or abort the other transaction.

Page 46: Software Transactional Memory

Summary

Pros and Cons of STM

Pros and Cons of DSTM

Discussion – what should the future concurrency framework look like?