Transactional Memory Guest Lecture Design of Parallel and High-Performance Computing Georg Ofenbeck...

40
Transactional Memory Guest Lecture Design of Parallel and High-Performance Computing Georg Ofenbeck

Transcript of Transactional Memory Guest Lecture Design of Parallel and High-Performance Computing Georg Ofenbeck...

Transactional MemoryGuest Lecture Design of Parallel and High-Performance Computing

Georg Ofenbeck

LS

Locking Recap: The Problemvoid PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }

Double queue

qn

10 20 RS

How to make this parallel? Global lock to coarse grained

Fine grained locking not trivial

How to compose?

? ? ?

?

void PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

LS

Locking Recap: A possible Solution

Double queue

qn

10 20 RS

Transactional Memory might be a solution Makes a code block behave like its executed as a single atomic instruction

Transaction

Historical Background Databases accessed concurrently for decades

“Transactions” as abstraction tool Atomic

Consistency

Isolated

Durable

Proposed for general applications already 1977 by Lomet Transactions on memory instead of databases

Picture: http://godatabase.net

Research on Transactional Memory

1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 20110

50

100

150

200

250

300

350

400

450

ACM digital li-brary

Google scholar hits

IeeeXplore

[Number of publications][Number of hits/10]

multicore

Research on Software TM (STM) Intel C++ STM compiler extends C++ with support for STM language

extensions

Microsoft STM.NET is an experimental extension of the .NET Framework

Sun/Oracle DSTM2 Dynamic Software Transactional Memory Library

void PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

LS

ACID

Double queue

10 20 RS

Transaction

void PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

LS

AtomicityCID

Double queue

qn

10

Failure atomicity Transaction only succeeds if all its parts succeed

No evidence of its execution is left behind in case of failure

Does not mean atomic executionTransaction

void PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

LS

AtomicityCID

Double queue

qn

10

Failure atomicity Transaction only succeeds if all its parts succeed

No evidence of its execution is left behind in case of failure

Does not mean atomic executionTransaction

void PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

AConsistencyID

Double queue

Consistency A consistent state (e.g. links ok) is preserved when transaction ends

In case of an abort satisfied by the failure atomicityTransaction LS

qn

10

void PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

ACIsolationD

Isolation Transaction do not interfere with each other

Transaction

LS

qn

qn

10

void PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

ACIsolationD

Double queue

Isolation Transaction do not interfere with each other

Transaction

void PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

ACIDurability

Durability Persisting data in the database world

Sometimes relevant for Hardware TM – persisting caches to memoryTransaction

TM Design Choices Failure Atomicity

How to restore the original state?

Version Control

Isolation How to shield concurrent transactions from each other?

Concurrency Control

Consistency How to detect conflicts?

Conflict Detection

TM Design Choices Failure Atomicity

How to restore the original state?

Version Control

Isolation How to shield concurrent thread from each other?

Concurrency Control

Consistency How to detect conflicts?

Conflict Detection

Version Controlvoid PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }} Eager Version Management

Write changes directly in memory and change all values in Undo Log

On success simply remove Undo Log

On failure restore original values

Version Control

Eager Version Management Write changes directly in memory and change all values in Undo Log

On success simply remove Undo Log

On failure restore original values

Undo Log

QNode *LSQNode *LNNULLNULL

LS

Double queue

qn

10

void PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

Version Controlvoid PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }} Lazy Version Management

Write changes into a buffer and apply at commit

Apply changes during commit if no conflict occurred

Otherwise just discard buffer

Most common

Version Control

Lazy Version Management Write changes into a buffer and apply at commit

Apply changes during commit if no conflict occurred

Otherwise just discard buffer

Most common

Buffer

LS

Double queue

qn

10

void PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

Version Control

Lazy Version Management Write changes into a buffer and apply at commit

Apply changes during commit if no conflict occurred

Otherwise just discard buffer

Most common

Buffer

x2

void Example () { x = 2; y = 0; atomic{

x = 3;y = x;

}}

y0

x3

?

Version Control Redirection

Explicit by library

Implicit by compiler

Overhead!

void PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val; do{ StartTx(); QNode *LS = ReadTx(&(q->left)); QNode *oLN = ReadTx(&(LS->left)); WriteTx(&(qn->left), LS); WriteTx(&(qn->right), oLN); WriteTx(&(LS->right), qn); WriteTx(&(oLN->left), qn); } while (!CommmitTx());}

TM Design Choices Failure Atomicity

How to restore the original state?

Version Control

Isolation How to shield concurrent transactions from each other?

Concurrency Control

Consistency How to detect conflicts?

Conflict Detection

Concurrency Controlvoid PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }} Pessimistic

Transaction locks all variables it works on during a transaction

LS

Concurrency Controlvoid PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

Double queue

qn

10

Pessimistic Transaction locks all variables it works on during a transaction

Deadlocks!

Usually in combination with eager version managment

qn

Concurrency Controlvoid PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }} Optimistic

System maintains multiple versions and detects conflict later

LS

Concurrency Controlvoid PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

Double queue

qn

10

Optimistic System maintains multiple versions and detects conflict later

qn

LS

Concurrency Controlvoid PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }}

Double queue

qn

10

Optimistic System maintains multiple versions and detects conflict later

Livelocks!

qn

Concurrency Controlvoid PushLeft (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LS->right = qn; LN->left = qn; }} Optimistic

System maintains multiple versions and detects conflict later

Livelocks!

void PushLeft2 (DQueue *q, int val) { QNode *qn = malloc(sizeof(QNode)); qn->val = val;

atomic{ QNode *LS = q->left; QNode *LN = LS->right; qn->left = LS; qn->right = LN; LN->left = qn; LS->right = qn; }}

TM Design Choices Failure Atomicity

How to restore the original state?

Version Control

Isolation How to shield concurrent transactions from each other?

Concurrency Control

Consistency How to detect conflicts?

Conflict Detection

Conflict detection Granularity

Bytes, Objects ….

How to resolve? Control to user? (Exception like)

RetryDelayedPriorities ….

For optimistic concurrency When to check?

Eager conflict detection?

How to detect?

void Example (int input) { atomic{

x = input;y = x;

}}

Nesting Flattened Nesting

Closed Nesting

Open Nesting

void Example () { x = 2; y = 0; atomic{ x = 3; y = x; atomic{ z = 3*x; w = z--; } }}

Why do we bother with locks?

Source: Calin Cascaval, Colin Blundell, Maged Michael, Harold W. Cain, Peng Wu, Stefanie Chiras, Siddhartha Chatterjee, 2008. Software Transactional Memory: Why Is It Only a Research Toy?.Queue 6, 5 (September 2008)

Why do we bother with locks?

Source: Calin Cascaval, Colin Blundell, Maged Michael, Harold W. Cain, Peng Wu, Stefanie Chiras, Siddhartha Chatterjee, 2008. Software Transactional Memory: Why Is It Only a Research Toy?.Queue 6, 5 (September 2008)

Why do we bother with locks?

Source: Aleksandar Dragojević , Pascal Felber , Vincent Gramoli , Rachid Guerraoui, Why STM can be more than a research toy, Communications of the ACM, v.54 n.4, April 2011

Why do we bother with locks?

Source: Ferad Zyulkyarov, Vladimir Gajinov, Osman S. Unsal, Adrián Cristal, Eduard Ayguadé, Tim Harris, and Mateo Valero. 2009. Atomic quake: using transactional memory in an interactive multiplayer game server.

Why do we bother with locks?

Source: Ferad Zyulkyarov, Vladimir Gajinov, Osman S. Unsal, Adrián Cristal, Eduard Ayguadé, Tim Harris, and Mateo Valero. 2009. Atomic quake: using transactional memory in an interactive multiplayer game server.

Why do we bother with locks?

1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 20110

50

100

150

200

250

300

350

400

450

ACM digital li-brary

Google scholar hits

IeeeXplore

[Number of publications][Number of hits/10]

Why do we bother with locks? Intel C++ STM compiler extends C++ with support for STM language

extensions

Microsoft STM.NET is an experimental extension of the .NET Framework

discontinued

Summary

TM is a nice model to tackle parallelism BUT STM does not yield good performance

HTM often with only limited functionality and hard to instrument

Hybrids the future?

Issues not covered in this lecture Details of conflict detection

How to handle I/O?

How to handle access from outside of the transaction?

….

More information Transactional Memory, 2nd Edition (Synthesis Lectures on Computer

Architecture)