Concurrent programming made simple The (r)evolution of transactional - - PowerPoint PPT Presentation
Concurrent programming made simple The (r)evolution of transactional - - PowerPoint PPT Presentation
Concurrent programming made simple The (r)evolution of transactional memory Torvald Riegel Nuno Diegues Red Hat INESC-ID, Lisbon, Portugal FOSDEM 2014 Concurrent programming Concurrent = at the same time and not independent Concurrent
FOSDEM 2014
Concurrent programming
- Concurrent = at the same time and not independent
– Concurrent actions need to synchronize with each other
Shared memory (synchronization) + Transactions = Transactional memory (TM)
- Atomicity enables synchronization
– Example: atomic HW instructions such as x86 cmpxchg – Database folks: think atomicity + isolation
FOSDEM 2014
TM is a programming abstraction
- Underlying vision: Allow programmers...
... to declare which code sequences are atomic ... instead of requiring them to implement how to make those atomic.
- Generic implementation ensures atomicity
– Not specific to a particular program – Purely SW, purely HW, or mixed SW/HW
- Our focus: TM for high-level programming languages
FOSDEM 2014
Agenda
- 1st part: TM for shared memory on a single machine
– C/C++ language constructs – A peek into GCC's implementation – Some notes on performance
- 2nd part: TM for distributed shared memory (multiple
machines)
– Importance of strong transactions – A framework for distributed applications
- Q & A
FOSDEM 2014
TM is still rather new
- Proposed 20 years ago
- Substantive research started 10 years ago, and ongoing
- Standardization for C/C++ started 5 years ago
– ISO C++ Study Group 5 on TM since mid 2012
- GCC support for C/C++ TM constructs since 4.7
- HW TM implementations: Azul, BlueGene/Q, Intel Haswell
FOSDEM 2014
C/C++ language constructs
- Declare that compound statements must execute atomically
–
__transaction_atomic { if (x < 10) y++; } – No data annotations or special data types required – Existing (sequential) code can be used in transactions:
function calls, nested transactions, ...
- Code in atomic transactions must be transaction-safe
– Compiler checks whether code is safe – Unsafe: use of locks or atomics, asm, volatile, functions not
known to be safe
– For cross-CU calls / function pointers, annotate functions:
void foo() __attribute__((transaction_safe)) { x++; }
- Further information: ISO C++ paper N3718
FOSDEM 2014
Synchronization semantics
- Transactions extend the C11/C++11 memory model
– All transactions totally ordered – Order contributes to memory model’s happens-before – TM ensures some valid order consistent with happens-before – Does not imply sequential execution at runtime!
- Data-race freedom still required (as with locks,...)
init(data); __transaction_atomic { data_public = true; } Correct: __transaction_atomic { if (data_public) use(data); } Incorrect: __transaction_atomic { temp = data; // Data race if (data_public) use(temp); }
FOSDEM 2014
TM supports modular programming
- Programmers don’t need to manage association between
shared data and synchronization metadata (e.g., locks)
– TM implementation takes care of that :-)
- Functions containing only txnal synchronization compose
without deadlock
– Nesting order of transactions does not matter – But can’t expect another thread to make progress in an
atomic transaction!
- Example: Synchronize moving an element between lists
void move(list& l1, list& l2, element e) { if (l1.remove(e)) l2.insert(e); }
– TM: __transaction_atomic { move(A, B, 23); } – Locks: ?
FOSDEM 2014
GCC’s implementation: Compiler
- Ensure atomicity guarantee (at compile time!)
– Find all transaction-safe code (implicitly or by annotation) – Check that transaction-safe code is indeed safe
- Create an instrumented clone of all transactional code
– Transaction-safe functions, code in transactions – Memory loads/stores rewritten to calls to TM runtime library – Function calls redirected to instrumented clones – Result: both an instrumented and uninstrumented code
path
- Generate begin/commit code for each transaction
– Runtime library decides whether to execute instrumented or
uninstrumented code path
- Delegation to runtime library = implementation flexibility
FOSDEM 2014
GCC’s implementation: TM runtime library (libitm)
- Enforces atomicity of transactions at runtime
- libitm contains different SW-only implementations (STM)
– Do not need special hardware – Default:
- Write-through with undo logging
- Multiple locks (automatic memory-to-lock mapping)
- Uses instrumented code path
- Using HW TM implementations (HTM)
– Current HTMs are all best-effort
- Not able to execute all txns, thus need a fallback (e.g., STM)
– libitm uses HTM with a global lock as fallback
- HW transactions use uninstrumented code path
– No hybrid STM/HTM yet
FOSDEM 2014
Performance: It’s a tool, not magic
- Performance goal:
A useful balance between ease-of-use and performance
- Not meaningful to try to draw conclusions about TM
performance today
– Implementations are work-in-progress (e.g., libitm,
HTMs, ...)
– Performance heavily influenced by many factors
- HW, compiler, TM algorithm, HTM implementation, allocator,
LTO or not, ...
- Txn conflict probability, txn length, load/store ratio in txns,
memory access patterns, data layout, allocation patterns,
- ther code executed in txns, ...
– Tuning for real-world workloads: chicken-and-egg situation
FOSDEM 2014
Performance: Rough estimates that are probably still true in the future
- Single-thread performance
– STM slower than sequential – STM slower (or equal) to coarse locking – HTM about as fast as uncontended critical section
- If HTM can run the transaction
- Multiple-thread performance
– STM scales well
- But less likely if low single-thread overhead
– HTM scales well
- Unless slower fallback needs to run frequently
– Hybrid STM/HTM: hopefully HTM performance with a
fallback that scales
- TM runtime libraries can adapt at runtime!
FOSDEM 2014
Ways to get involved
- Use it
– Try it out (gcc -fgnu-tm), measure performance for your
code, read the C++ specification (N3718 / N3859), ...
- Report about your findings and experience
– Blog about it and let us know, report bugs in the GCC
implementation, ...
- Get involved in ISO C++ TM standardization (SG5)
– http://isocpp.org/forums
- Dive into libitm / GCC
– Extensive comments in the libitm code – Many interesting things to work on (e.g., improving the
(auto-)tuning)
FOSDEM 2014
The Cloud-TM Approach The Cloud-TM Approach
14
FOSDEM 2014
FOSDEM 2014
Moving to a distributed world Moving to a distributed world
Quad-core machine
FOSDEM 2014
Moving to a distributed world Moving to a distributed world
Quad-core machine Quad-core machine Quad-core machine
Shared Memory Abstraction via Network
D i f f e r e n t e n v i r
- n
m e n t , D i f f e r e n t e n v i r
- n
m e n t , s a m e a b s t r a c t i
- n
! s a m e a b s t r a c t i
- n
!
FOSDEM 2014
Distributed Transactional Memory Distributed Transactional Memory
17
FOSDEM 2014
Similarly to TM: Bring transactions to the top of the stack Dynamic transactions Straight in the app logic Long-lived transactions Difgerent from TM: Persistence Distribution Fault-tolerance
FOSDEM 2014
Distributing Data Distributing Data
18
FOSDEM 2014
Not fault Not fault tolerant tolerant
Our data:
F u l l R e p l i c a t i
- n
F u l l R e p l i c a t i
- n
P a r t i a l R e p l i c a t i
- n
P a r t i a l R e p l i c a t i
- n
FOSDEM 2014
Why strong consistency? Why strong consistency?
19
FOSDEM 2014
Eventual Consistency → no consistency
change
replicate
read
FOSDEM 2014
Why serializable transactions? Why serializable transactions?
20
Snapshot Isolation
W r i t e
- s
e t s d
- n
- t
i n t e r s e c t : W r i t e
- s
e t s d
- n
- t
i n t e r s e c t : w r i t e
- s
k e w a n
- m
a l y w r i t e
- s
k e w a n
- m
a l y
FOSDEM 2014
FOSDEM 2014
The Cloud-TM Approach The Cloud-TM Approach
21
FOSDEM 2014
Embraces distribution
Serializable transactions Partial replication Scalable solution
T argets many common use cases
Simple bootstrap Details hidden from programmer Easy management Fast/scalable enough
FOSDEM 2014
The Cloud-TM Approach The Cloud-TM Approach
22
FOSDEM 2014
DSL to specify Object-Oriented domain model Hides: Concurrency control Persistence Data Placement OO view of: Distributed execution Data locality API for expert programmers
FOSDEM 2014
PhoneBook
From design to code From design to code
23
FOSDEM 2014
bookId name contact Contact contactId email phone
n n
Entities → (Java) Classes Relationships → Collections/References Bidirectional updates T
ype of collection used
...
FOSDEM 2014
PhoneBook
From design to code From design to code
24
FOSDEM 2014
bookId name contacts Contact contactId email phone
n n
@Entity class PhoneBook { @Id @GeneratedValue public String bookId; public String name; @ManyToMany public Set<Contact> contacts; } @Entity class Contact { @Id @GeneratedValue public String contactId; public String email; public String phone; @ManyToMany(mappedBy=”contacts”) public Set<PhoneBook> books; }
C a n w e m a k e i t s i m p l e r ? C a n w e m a k e i t s i m p l e r ?
FOSDEM 2014
Domain Modeling Language Domain Modeling Language
25
FOSDEM 2014
Programmer describes: Entities Relationships DML is a DSL
FOSDEM 2014
PhoneBook
From design to code From design to code
26
FOSDEM 2014
bookId name contact Contact contactId email phone
n n
class Contact { String email; String phone; } class PhoneBook { String name; } relation PhoneBooksHaveContacts { PhoneBook playsRole book { multiplicity *; } Contact playsRole contact { multiplicity *; } }
FOSDEM 2014
Domain Modeling Language Domain Modeling Language
27
FOSDEM 2014
Programmer describes: Entities Relationships DML is a DSL Framework generates code with:
Well known interface Entities → Classes with getters / setters Relations → Management methods on both sides
FOSDEM 2014
Generating the code Generating the code
28
FOSDEM 2014
FOSDEM 2014
Generating the code Generating the code
29
FOSDEM 2014
class PhoneBook { String getName(); void setName(String name); Set<Contact> getContactSet(); void addContact(Contact contact); void removeContact(Contact contact); ... } class Contact { String getEmail(); void setEmail(String email); Set<PhoneBook> getBookSet(); void addBook(PhoneBook book); void removeBook(PhoneBook book); }
I n t e r f a c e I n t e r f a c e r e m a i n s r e m a i n s t h e s a m e t h e s a m e A c t u a l A c t u a l c
- d
e c
- d
e v a r i e s v a r i e s
FOSDEM 2014
Generating the code Generating the code
30
FOSDEM 2014
FOSDEM 2014
Mapping to Persistence Mapping to Persistence
31
FOSDEM 2014
Application Domain Objects K V Tx1 Tx2
P r
- g
r a m m e r s P r
- g
r a m m e r s a r e n
- t
a w a r e
- f
t h i s a r e n
- t
a w a r e
- f
t h i s D i f f e r e n t p e r s i s t e n c y D i f f e r e n t p e r s i s t e n c y b a c k e n d s b a c k e n d s
FOSDEM 2014
Using the code Using the code
32
FOSDEM 2014
@Scoped(REQUEST) public class BookService { @Inject EntityManager em; @Transactional public PhoneBook createBook(String name) { PhoneBook book = new PhoneBook(); book.name = name; em.persist(book); return book; } @Transactional public addContact(String bookId, String email) { PhoneBook book = em.find(PhoneBook.class, bookId); Contact contact = new Contact(); contact.email = email; contact.addBook(book); book.addContact(contact); em.persist(contact); } }
FOSDEM 2014
Using the code Using the code
33
FOSDEM 2014
public class BookService { @Atomic public PhoneBook createBook(String name) { PhoneBook book = new PhoneBook(); book.setName(name); return book; } @Atomic public addContact(String bookId, String email) { PhoneBook book = App.getBookById(bookId); Contact contact = new Contact(); contact.setEmail(email); book.addContact(contact); } }
FOSDEM 2014
Configuring the App Configuring the App
34
FOSDEM 2014
fenix-framework.properties: appName = phonebook # configurations for backend-infinispan ispnConfigFile = infinispan.xml expectedInitialNodes = 2 jgroupsConfigFile = jgroups.xml
FOSDEM 2014
jgroups.xml: <config> <TCP ... /> <MERGE2 ... /> <FD_SOCK/> <BARRIER/> <pbcast.NAKACK2 ... /> <UNICAST2 ... /> ... </config>
Configuring the App Configuring the App
P r e
- b
u i l t c
- n
f i g u r a t i
- n
s P r e
- b
u i l t c
- n
f i g u r a t i
- n
s
FOSDEM 2014
Configuring the App Configuring the App
36
FOSDEM 2014
ispn.xml: <infinispan> <default> <locking isolationLevel="SERIALIZABLE"/> <transaction lockingMode="OPTIMISTIC"/> <clustering mode="distributed"> <l1-cache enabled="true"/> </clustering> <versioning enabled="true" versioningScheme="GMU" /> </default> <namedCache name="phoneCache" /> </infinispan>
FOSDEM 2014
Configuring the App Configuring the App
37
FOSDEM 2014
ispn.xml: <infinispan> <default> <locking isolationLevel="REPEATABLE_READ" writeSkewCheck="true"/> <transaction lockingMode="PESSIMISTIC"/> <clustering mode="replicated"/> <versioning enabled="true" versioningScheme="SIMPLE" /> </default> <namedCache name="phoneCache" /> </infinispan>
FOSDEM 2014
Compile & run Compile & run
38
FOSDEM 2014
mvn clean package -Dcode.generator=Infinispan
- or -
mvn clean package -Dcode.generator=HibernateOgm mvn exec:java -Dexec.mainClass="MainApp"
S e v e r a l u n i v e r s i t i e s r u n n i n g i t S e v e r a l u n i v e r s i t i e s r u n n i n g i t
FOSDEM 2014
Advanced Features Advanced Features
39
FOSDEM 2014
Indexed relations Data (co-)location Data-Oriented execution Hibernate Search Ghost reads Concurrency-friendly collections L1 and L2 object caches
FOSDEM 2014
Indexed Relations Indexed Relations
40
FOSDEM 2014
class Contact { String email; String phone; } class PhoneBook { String name; } relation PhoneBooksHaveContacts { PhoneBook playsRole book { multiplicity *; } Contact playsRole contact { multiplicity *; indexed by email; } } PhoneBook bookId name contact Contact contactId email phone
n n
PhoneBook workBook = (…) // get the book for (Contact ct : workBook.getContactSet()) { if (ct.getEmail().equals(givenEmail)) { ct.disable(); return; } } PhoneBook workBook = (…) // get the book workBook.getContactByEmail(givenEmail).disable(); return;
FOSDEM 2014
Data Location Data Location
41
FOSDEM 2014
int countryCode = extractCode(phone); LocalityHints hints = new LocalityHints(“code”, countryCode); Contact ct = new Contact(email, phone); // where does it go?
FOSDEM 2014
Data-Oriented Execution Data-Oriented Execution
42
FOSDEM 2014
public class DistributedTask implements Callable, Serializable { Contact ct; public DistributedTask(Contact ct) { this.ct = ct; } @Atomic public void call() { // execution is migrated to machine replicating “ct” } } (…) Callable task = new DistributedTask(ct); executor.submit(task, FF.getLocality(ct));
FOSDEM 2014
Data (Co-)Location Data (Co-)Location
43
FOSDEM 2014
int countryCode = extractCode(phone); LocalityHints hints = new LocalityHints(“code”, countryCode); // use hints to place it Contact ct = new Contact(hints, email, phone); // ct and otherCt are co-located Contact otherCt = new Contact(hints, emailOther, phoneOther);
By default objects of a given relation are co-located
FOSDEM 2014
In summary In summary
44
FOSDEM 2014
Distributed programs are hard to develop Low-level mechanisms make it harder API should hide complexity, whenever possible Do not limit expressiveness, whenever needed
FOSDEM 2014
References References
45
FOSDEM 2014
Cloud-TM stack:
www.cloudtm.eu
Fénix Framework:
http://fenix-framework.github.io
FénixEdu:
http://fenixedu.org
Get involved..! Get involved..!
46
FOSDEM 2014
Research network: Industry + Academia
47
FOSDEM 2014
If you are interested in TM: Euro-TM can fund your participation
Workshops: Amsterdam 13 April'14 Training Schools: La Plagne 16-21 March'14 Collaborations / Joint works 1-3months to visit another EU institution