==== Aufgabe 1 (Wissensfragen) ====
a) falsch
b) richtig (z. B. durch Prüfe-Handle-Situationen)
c) falsch
d) falsch
e) richtig
f) Speedup = 6, Effizienz = 3/4
g) falsch (Null ist lediglich Untertyp aller AnyRef-Typen, Nothing ist Untertyp aller Scala-Typen)
====Aufgabe 2 (Petri-Netze) ====
a)
S:
(1, 1, 0, 0, 0) (Transponiert)
M:
(-1, 0, 0, 0, 1)
( 1, 2, -1, -1, 0)
( 0, -1, 1, 0, 0)
( 0, -1, 0, 1, 0)
( 0, -1, 0, 1, -1)
b)
t1 -> t4 -> t3 -> t5
c) Ja
d) E: (0, 7, 0, 0)
====Aufgabe 3 (Java - Präfixsumme) ====
a) Gauß-Filter / Weichzeichner (? -> eher Zeigerverdopplung)
import java.util.concurrent.*;
public class ParallelPrefixSums {
private static CyclicBarrier barrier;
public static void calculateSums(int[] values) throws InterruptedException {
barrier = new CyclicBarrier(values.length);
Thread[] workers = new Thread[values.length];
for (int i = 0; i < values.length; i++) {
workers[i] = new Thread(new Worker(values, i));
workers[i].start();
}
for (int i = 0; i < values.length; i++) {
workers[i].join();
}
}
public static class Worker implements Runnable {
private int[] values;
private int index;
public Worker (int[] values, int index) {
this.values = values;
this.index = index;
}
public void run() {
try {
int distance = 1;
while (distance < values.length) {
barrier.await();
int target = index + distance;
int rem = values[index];
barrier.await();
if (target < values.length) {
values[target] += rem;
}
dist *= 2;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
==== Aufgabe 4 (Schreibtischlauf - Barrieren) ====
* a) a = 1, weil sowohl a++ als auch die System.out.println-Ausgabe in einem synchronized-Block stehen und beide Threads auf dieselbe Marke synchronisieren.
* b) Mögliche Ausgaben sind:
a=1
a=2
a=3
Threads 1, 2, 3 started.
Und
a=1
a=2
Threads 1, 2, 3 started.
a=3
Der Main-Thread synchronisiert nicht auf irgendeine Marke (insb. nicht auf BarrierTest.class), daher erscheinen ihm die synchronized-Blöcke der Threads nicht als unteilbare Einheit und er kann bereits nach a++, aber vor System.out.println die While-Schleife verlassen.
* c) 1, 2, 3, oder 4 Mal. Jeder Thread könnte gleichzeitig b=0 am Anfang feststellen oder erst prüfen, nachdem die anderen Threads (oder ein Teil davon) das IF verlassen.
* d) Vorletzte oder letzte Zeile. Der CountDownLatch ist nur mit 3 initialisiert worden. Daher kann sich der letzte Thread irgendwo zwischen barrier.await() und latch.countDown() befinden.
==== Aufgabe 5 (Scala - Snake-Sort) ====
sortAsc, sortDes waren nicht Teil der Aufgabe, sind aber zum Testen implementiert.
import System.{ currentTimeMillis => ct }
type Row = List[Int]
type Matrix = List[Row]
def sortAsc: Row => Row = rs => if(rs == Nil) Nil else rs.min :: sortAsc(rs.filter(_ > rs.min))
def sortDes: Row => Row = rs => if(rs == Nil) Nil else rs.max :: sortDes(rs.filter(_ < rs.max))
def sortCols: Matrix => Matrix = m =>
(for(col <- m.transpose) yield sortAsc(col)).toList.transpose
def sortColsPar: Matrix => Matrix = m => (for(col<- m.transpose.par) yield sortAsc(col)).toList.transpose
// Alternativ (laut #Scala ist die Paralleliät bei beiden äquivalent gegeben):
def sortColsPar2: Matrix => Matrix = m => m.transpose.par.map(sortAsc(_)).toList.transpose
def sortRows: Matrix => Matrix = m =>{
def helper: (Matrix, Int) => Matrix = {
case (Nil, n) => Nil
case (m::ms, n) if(n % 2 == 0) => sortAsc(m)::helper(ms,n+1)
case (m::ms, n) if(n % 2 != 0) => sortDes(m)::helper(ms,n+1)
}
helper(m,0)
}
//Alternative ohne Helfer-Funktion:
def sortRows2: Matrix => Matrix = m => m match {
case Nil => Nil
case (row::m) => if (m.length % 2 == 0)
sortAsc(row)::sortRows2(m)
else
sortDes(row)::sortRows2(m)
}
def sortHelper: (Int, Matrix) => Stream[(Matrix,Matrix)] = {
case (n,m) => if (n%2==0) (m, sortRows(m)) #::sortHelper(n+1,sortRows(m)) else (m,sortCols(m)) #::sortHelper(n+1,sortCols(m))
}
def snakeSort: Matrix => Matrix = m => {
def helper: (Matrix, Int) => Matrix = (m,n) => {
val a = sortHelper(0,m)(n)
if(a._1 == a._2) a._2 else helper(m,n+1)
}
helper(m,0)
}
==== Aufgabe 6 ====
Nicht mehr Teil des Vorlesungsstoffes.