Proseminar Nichtsequentielle Programmiersprachen

Ähnliche Dokumente
Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 11/12 1. Kapitel 11. Listen. Listen

Java Concurrency Utilities

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 16/17. Kapitel 13. Listen. Listen 1

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 15/16. Kapitel 12. Listen. Listen 1

Schnittstellen, Stack und Queue

Schwerpunkte. Verkettete Listen. Verkettete Listen: 7. Verkettete Strukturen: Listen. Überblick und Grundprinzip. Vergleich: Arrays verkettete Listen

Verkettete Datenstrukturen: Listen

6. Verkettete Strukturen: Listen

Dynamische Datentypen. Destruktor, Copy-Konstruktor, Zuweisungsoperator, Dynamischer Datentyp, Vektoren

13. Dynamische Datenstrukturen

Linked Lists The Role of Locking

II.4.5 Generische Datentypen - 1 -

12 Abstrakte Klassen, finale Klassen und Interfaces

Verschlüsseln eines Bildes. Visuelle Kryptographie. Verschlüsseln eines Bildes. Verschlüsseln eines Bildes

II.4.2 Abstrakte Klassen und Interfaces - 1 -

ALP II Dynamische Datenmengen

3. Übungsblatt zu Algorithmen I im SoSe 2017

Algorithmen und Datenstrukturen

Institut für Informatik

Abgabe: (vor 12 Uhr)

Programmierkurs Java

Programmieren in Java

Programmieren in C. Rekursive Strukturen. Prof. Dr. Nikolaus Wulff

14 Abstrakte Klassen, finale Klassen, Interfaces

Einstieg in die Informatik mit Java

14 Abstrakte Klassen, finale Klassen, Interfaces. Auswertung von Ausdrücken. Beispiel. Abstrakte Methoden und Klassen

Informatik II Übung 5

Arrays. Gilbert Beyer und Annabelle Klarl. Einführung in die Informatik. Zentralübung zur Vorlesung Einführung in die Informatik

! 1. Unterklassen und Vererbung! 2. Abstrakte Klassen und Interfaces! 3. Modularität und Pakete. II.4.2 Abstrakte Klassen und Interfaces - 1 -

Nachname: Vorname: Matr.-Nr.: Punkte: 1. Aufgabe: ( / 25 Pkt.) Gegeben ist das folgende Struktogramm zur Berechnung von sin(x) mit Hilfe einer Reihe.

Visuelle Kryptographie. Anwendung von Zufallszahlen

Innere Klassen. Innere Klassen. Page 1. Lernziele: innere Klassen, statische geschachtelte Klassen, anonyme Klassen.

class ListElement { int value; ListElement next; ListElement() { next=null; value=0;

EINFÜHRUNG IN DIE PROGRAMMIERUNG

Prozesszustände (1a)

Ausnahmebehandlung in Java

Interface. So werden Interfaces gemacht

II. Grundlagen der Programmierung. Beispiel: Merge Sort. Beispiel: Merge Sort (Forts. ) Beispiel: Merge Sort (Forts. )

Algorithmen und Datenstrukturen II

Grundlagen der Informatik 0

Problem: Was ist, wenn der Stapel voll ist? Idee: Erzeuge dynamisch ein grösseres Array und kopiere um. Dynamische Anpassung der Größe

II.4.4 Exceptions - 1 -

Objektorientierte Programmierung Studiengang Medieninformatik

Stacks, Queues & Bags. Datenstrukturen. Pushdown/Popup Stack. Ferd van Odenhoven. 19. September 2012

! 1. Rekursive Algorithmen.! 2. Rekursive (dynamische) Datenstrukturen. II.3.2 Rekursive Datenstrukturen - 1 -

7.0 Arbeiten mit Objekten und Klassen

ADT: Verkettete Listen

Grundzüge der Wirtschaftsinformatik WS 2002/03. Wiederholung Java. Programmierzyklus. Heiko Rossnagel Problem

Seminar "Ausgewählte Themen in Hardwareentwurf und Optik" im HS Transactional Memory. Vortrag von Erdin Sinanović

Prof. Dr. Uwe Schmidt. 30. Januar 2017

Algorithmen und Programmierung II

Arrays (Reihungen) Arrays (Reihungen) in Java: Syntax, Typisierung, Semantik.

Programmierung mit C Zeiger

Advanced Programming in C

Transactional Memory. Robert Brunel Technische Universität München

Programmieren I. Kapitel 13. Listen

Zentralübung Grundlagen der Programmierung

System.out.println("TEXT");

Einführung in die Programmierung

Algorithmen und Datenstrukturen Musterlösung 5

Algorithmen und Datenstrukturen

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

Algorithmen und Programmierung III

Verkettete Listen. DVG Verkettete Listen 1

Geordnete Binärbäume

Eine Klasse beschreibt Objekte mit gleichen Attributen und Methoden.

Programmieren 2 Java Überblick

Betriebssysteme. Vorlesung im Herbstsemester 2010 Universität Mannheim. Kapitel 6: Speicherbasierte Prozessinteraktion

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 16/17. Kapitel 14. Bäume. Bäume 1

Fachgebiet Softwaretechnik, Heinz Nixdorf Institut, Universität Paderborn. Testen. Tutorial im Rahmen des Software(technik)praktikums SS 2012

Zur Erinnerung: Threads. Threadverwaltung. Threads: Prioritäten. Beispiel Flugbuchungsprogramm. Nichtdeterminismus

Algorithmen implementieren. Implementieren von Algorithmen

Allgemeine Hinweise:

Praxis der Programmierung

Software Entwicklung 1

CoMa 04. Java II. Paul Boeck. 7. Mai Humboldt Universität zu Berlin Institut für Mathematik. Paul Boeck CoMa 04 7.

Javakurs FSS Lehrstuhl Stuckenschmidt. Tag 3 - Objektorientierung

Übungsblatt Programmierung und Software-Entwicklung Generizität, Interfaces, Listen, Sortieralgorithmen & JUnit

Computergrundkenntnisse und Programmieren, WS 07/08, Übung 11: Klassen der Standardbibliothek 2

Probeklausur: Programmierung WS04/05

Aufgabe 1 (Programmanalyse, Punkte)

Gliederung. 5. Compiler. 6. Sortieren und Suchen. 7. Graphen

4. Algorithmen und Datenstrukturen I Grundlagen der Programmierung 1 (Java)

Beuth Hochschule Parameter-Übergabe-Mechanismen WS17/18, S. 1

Lösungsvorschlag Serie 2 Rekursion

Einführung in C. EDV1-04C-Einführung 1

Welche Informatik-Kenntnisse bringen Sie mit?

Kapitel 9. Programmierkurs. Attribute von Klassen, Methoden und Variablen. 9.1 Attribute von Klassen, Methoden und Variablen

Präfix-Summe. Das Schweizer Offiziersmesser der Parallelen Algorithmen. Parallele Rechenmodelle Präfix-Summe Brents Lemma Anwendungen

Vorlesung Datenstrukturen

Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften

Wintersemester 2004/ Dezember 2004

Einstieg in die Informatik mit Java

13. Bäume: effektives Suchen und Sortieren

Tag 8 Repetitorium Informatik (Java)

Philipp Güttler Progwerkstatt Letzte Änderung: Enums, Interfaces, Generics und Threads

FH D. Objektorientierte Programmierung in Java FH D FH D. Prof. Dr. Ing. André Stuhlsatz. Referenzen. Referenzen

4.4.1 Implementierung vollständiger Bäume mit Feldern. Reguläre Struktur: Nachfolger des Knoten i sind die Knoten 2*i und 2*i+1.

Klausur Programmieren 2 SS 2016

Transkript:

Proseminar Nichtsequentielle Programmiersprachen WS 2011/2012 Software Transactional Memory Gregor Busse 04.01.2012 1

Inhaltsverzeichnis Software Transactional Memory: Einleitung..Seite 3 Software Transactional Memory nach Nir Shavit und Dan Touitou Seite 3 Algorithmus. Seite 4 Performance von STM. Seite 5 DSTM2 und Anwendungsbeispiel. Seite 6 Quellen. Seite 7 Anhang. Seite 7 2

Einleitung: Als Mittel zur Synchronisierung von Zugriffen auf geteilte Ressourcen haben wir bereits Semaphoren und Monitore kennengelernt. Beide Verfahren haben dabei eine steigende Komplexität mit der Anzahl an zu synchronisierende Prozessen und Ressourcen gemein. Ein weiteres Konzept zur Synchronisierung stellt Transactional Memory dar. Transaktionen kennen wir bereits von Datenbanken. Zugriffe auf Datenbanken (Lesen und Schreiben) werden entweder erfolgreich durchgeführt ( Commit ) oder abgebrochen ( Abort ) und müssen gegebenenfalls wiederholt werden. Ziel einer Datenbank ist dabei, die Wahrung der Datenkonsistenz bei gleichzeitig performanter Verarbeitung von möglichst vielen Zugriffen auf große Datenbestände. Die Entwicklung erfordert mit steigenden Prozessorzahlen gut skalierende Konzepte zur Verwaltung der geteilten Ressourcen bzw. des geteilten Speichers. Eine Möglichkeit ist dabei Transactional Memory (TM), die Anwendung des Konzepts der Datenbanktransaktion auf den Speicher eines Computers. TM lässt sich dabei sowohl in Hardware als auch in Software implementieren. Während Hardware Transactional Memory (HTM) potentiell die bessere Performance bietet (wie üblich bei festverdrahteten Funktionen) lässt dessen Verfügbarkeit noch zu wünschen übrig. Existierende Implementierungen sind experimenteller Natur. Erst kommende Prozessorgenerationen wie IBM BlueGene/Q oder Intel Haswell Prozessoren sollen mit HTM ausgestattet sein. Im Folgenden wollen wir daher Software Transactional Memory (STM) betrachten und eine mögliche Implementierung in Java. Software Transactional Memory nach Nir Shavit und Dan Touitou STM [1] als Konzept zur Synchronisierung von geteiltem Speicher, auf höherer Abstraktionsebene als Semaphoren und Monitoren, besitzt keine klassische kritische Sektion. Es ist ein optimistisches nonblocking/lock-free Verfahren unter Verwendung des Load_Linked/Store_Conditional Befehls. Ein Speicherbereich wird als Transactional Memory definiert. Prozesse und deren Transaktionen müssen von den Teilen des TM, welche sie benötigen, den Besitz erwerben. Dabei sind die einzelnen Speicherstellen des TM aufsteigend nummeriert/sortiert. Die Inbesitznahme durch Transaktionen erfolgt sequentiell von deren niedrigstem bis zum höchsten benötigtem Speicherbereich. Eine abgeschlossene Transaktion gibt anschließend ihren Speicher wieder frei. Daraus ergibt sich die non-blocking Eigenschaft dieser STM-Implementierung. Eine Transaktion T1 welche den Besitz einer Speicherstelle nicht erwerben kann, weil eine Transaktion T2 ihr zuvor kam kann T2 im weiteren Verlauf nicht blockieren. T2 besitzt alle benötigten niedrigeren Speicherstellen schon und T1 kann keine höhere Speicherstelle besitzen als die an der sie gescheitert ist. Nur eine Transaktion T3, welche höhere Speicherstellen besitzt die T2 benötigt, kann T2 zum Abbruch bringen. Letztendlich wird jene Transaktion, welche zuerst die höchsten von mehreren Transaktionen gleichzeitig benötigten Speicherstellen besitzt erfolgreich abschließen. Alle anderen hat sie schon in Besitz genommen und keine weitere Transaktion benötigt eine höhere Speicherstelle. 3

Eine Prozess, welcher seine Transaktion T1 wegen Absturz, Kontextwechsel etc. nicht abschließen kann, aber bereits Speicherbereich in Besitz genommen hat, würde andere Prozesse und deren Transaktionen auf den selben Speicherbereich blockieren. Um dies zu vermeiden, versuchen die blockierten Prozesse selbst T1 abzuschließen. Sie ermitteln die blockierende Transaktion und starten sie einmalig neu. Solange noch wenigstens ein lauffähiger Prozess im System versucht, wiederholt seine Transaktion durchzuführen, wird er in endlich vielen Schritten Erfolg haben. Mit jedem Versuch seiner Transaktion wird er eine blockierte Transaktion (von einem blockiertem Prozess) abschließen und somit deren Speicherbereich freigeben. Algorithmus (gekürzt): TM besteht aus einem Feld Memory[M], welcher die Daten enthält und einem Feld Ownerships[M], welches jeder Stelle in Memory einen Besitzer zuordnet. Prozesse die Transaktionen auf Memory ausführen wollen besitzen: - ein Variable Size, welche die Anzahl an benötigten Speicherstellen angibt. - ein Feld Add[], welches die Adressen der Speicherstellen enthält. -Eine Variable Input, als Eingabewerte der Transaktion. -ein Feld Oldvalues[], initialisiert mit Null und gefüllt mit gelesenen Werten bei erfolgreich ablaufender Transaktion. - Eine Variable Status welche: -mit NULL für initialisiert ist für Transaktionen welche noch nicht alle benötigten Speicherstellen besitzen. -Failure enthält, falls eine Speicherstelle nicht in Besitzt genommen werden konnte. -Success enthält, falls alle Speicherstellen in Besitz genommen werden konnten. StartTransaction(input,DataSet) Initialize(Tran,input,DataSet) Tran->Stable = TrueA Transaction(Tran,Tran->Version,True) Tran->Stable = False Tran->Version++ If Tran->Status = Success then return(sucess,calcoutput(tran->oldvalues,input)) return Failure Transaction(tran,version,IsInitiator) AcquireOwnerships(tran,version) (status,failadd) = LL(tran->status) If status = Null then If(version!= tran->version then return SC(tran->status,(Success,0) (status,failadd) = LL(tran->status) If status = Success then AgreeOldValues(tran,version) NewValues = CalcNewValues(tran->OldValues, tran->input) UpdateMemory(tran,version,NewValues) ReleaseOwnership(tran,version) 4

ReleaseOwnership(tran,version) If IsInitiator then failtran = Ownership[failadd] if failtran = Nobody then return failversion = failtran->version if failtran->stable Transaction(failtran,failversion,False) Performance von STM: Der Vergleich von STM mit anderen non-blocking Methoden für nicht optimierte Versionen der Algorithmen. Herlihy s method [1, 2]: Kopieren des geteilten Speicherbereichs, Operation auf Kopie ausführen, Pointer des geteilten Speicherbereichs auf Kopie setzten. Engpass: Kopieren großer Speicherbereiche. Cooperative method[1,3]: An Sperren gescheiterte Prozesse helfen rekursiv (der Abhängigkeitskette entlang) den Inhabern der Sperre ihre Operationen auszuführen. Engpass: Rekursiver Hilfs-Overhead. Throughput ratio of STM/other Herlihy s method Counter Bus 0,34 Alewife 0,30 Double linked queue Bus 6,07 Alewife 2,44 Resource Allocation Bus 22,5 Alewife 24,14 Priority queue Bus 0,42 Alewife 0,41 1,98 1,92 1,44 1,75 1,09 1,12 1,26 1,27 (Bus= klassisches Mehrkern System, Alewife= Netzwerkspeicher ) 10 processors 60 processors Cooperative Herlihy s method method 0,74 0,45 58,9 12,9 85,61 59,8 2,8 1,1 Eindeutig zu sehen ist die bessere Skalierung vom STM mit steigender Anzahl an Prozessoren. Cooperative method 8,44 7,6 3,36 7,28 1,69 2,35 2,16 2,24 5

DSTM2: DSTM2 [4] ist eine Java-Bibliothek, welche ein Framework zur einfachen Benutzung von Software Transactional Memory erlaubt. Hierzu bietet DSTM2 factories. Diese erstellen Objekte, welche nach dem Konzept des STM synchronisieren. Anwendungsbeispiel: Erstellen eines Interface Node für Objekte, die mittels STM synchronisieren und somit geteilt nutzbar sind: @atomic public interface INode{ int getvalue(); void setvalue(int value); INode getnext(); void setnext(inode value); } Erstellen einer Factory, welche Objekte vom Typ Node erstellen kann: Factory <INode> factory = dstm2.thread.makefactory(inode.class); Das Erstellen eines Objektes vom Typ Node kann nun die factory übernehmen: INode node = factory.create(); Exemplarisch wollen wir nun eine Node mit einem Wert in eine verkettete Liste einfügen. Der Aufruf der Transaktion mittel DSTM2 lautet: result = Thread.doIt(new Callable <Boolean>(){ public Boolean call(){ return alist.insert(value); } } doit lößt hier die eigentlich Transaktion aus und wird bis zum Erfolg oder Abbruch durch Exception wiederholt. alist ist ein Objekt einer gewöhnlichen Klasse, mit den üblichen Methoden zu Verwaltung einer verketteten Liste. Einzige Ausnahmen sind die Verwendung der DSTM2 Factory und @atomic INode Objekte: public class List{ static Factory <INode> factory = Thread.makeFactory(INode.class); public boolean insert(int v){ INode newnode = factory.create(); newnode.setvalue(v); //...newnode.setnext etc //...return true/false public int remove(){ //... }//... Durch die Verwendung der DTSM2 Factory und @atomic INode können schließlich beliebige Prozesse auf die verkettete Liste alist mittels doit zugreifen, ohne sich um die Synchronisierung kümmern zu müssen. 6

Quellen: [1] Nir Shavit and Dan Touitou. Software Transactional Memory [2] M. Herlihy. A methodology for implementing highly concurrent data objects. [3] A. Israeli and L Rappoprt. Disjoint-Access-Parallel Implementations of Strong Shared Memory [4] Maurice Herlihy, Victor Luchangco, Mark Moir. A Flexible Framework for Implementing Software Transactional Memory [5] http://en.wikipedia.org/wiki/transactional_memory [6] http://en.wikipedia.org/wiki/software_transactional_memory Anhang: Vollständiger STM Algorithmus von Shavit und Touitou: StartTransaction(input,DataSet) Initialize(Tran,input,DataSet) Tran->Stable = TrueA Transaction(Tran,Tran->Version,True) Tran->Stable = False Tran->Version++ If Tran->Status = Success then return(sucess,calcoutput(tran->oldvalues,input)) return Failure Transaction(tran,version,IsInitiator) AcquireOwnerships(tran,version) (status,failadd) = LL(tran->status) If status = Null then If(version!= tran->version then return SC(tran->status,(Success,0) (status,failadd) = LL(tran->status) If status = Success then AgreeOldValues(tran,version) NewValues = CalcNewValues(tran->OldValues, tran->input) UpdateMemory(tran,version,NewValues) ReleaseOwnership(tran,version) ReleaseOwnership(tran,version) If IsInitiator then failtran = Ownership[failadd] if failtran = Nobody then return failversion = failtran->version if failtran->stable Transaction(failtran,failversion,False) 7

AquireOwnerships(tran,version) transize = tran->size for i = 1 to size do while true do location = tran->add[i] if LL(tran->status)!= Null then return owner = LL (Ownershipüs[tran->Add[i]]) if tran->version!= version return if owner = tran then exit while loop if owner = Nobody then if SC(tran->status, (Null, 0)) then if SC(Ownerships[location], tran) then exit while loops if SC(tran->status, (Failure,i)) then return ReleaseOwnerships(tran, version) size = tran->size for i = 1 to size do location = tran->add[i] if LL(Ownerships[location]) = tran then if tran->version!= version then return SC(Ownerships[location], Nobody) AgreeOldValues(tran, version) size = tran->size for i = 1 to size do location = tran->add[i] if LL(tran->OldValues[location])!= Null then if tran->version!= version then return SC(tran->OldValues[location], Memory[location]) UpdateMemory(tran, version, newvalues) size = tran->size for i = 1 to size do location = tran->add[i] oldvalue = LL(Memory[location]) if tran->allwritten then return if version!= tran->version then return if version!= newvalues[i] then SC(Memory[location], newvallues[i]) if(not LL(tran->AllWritten)) then if version!= tran->version then return SC(tran->AllWritten, True) 8