Simulationssystem: Unterschied zwischen den Versionen
(Die Seite wurde neu angelegt: „= Zielsetzung = Simulation in einem Netz mit 10E9 Punkten. Dies setzt hohe Effizienz voraus, sowohl in Datenhaltung als auch in Programmperformance. Höchste…“) |
|||
(5 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 17: | Zeile 17: | ||
Beispiel: Daten pro Punkt 1000 Byte, Punkte: 20000*50000 = 1E9, Arbietsspeicher 500 GByte: Aufteilung in 2 Paritionen mit 20000*25000 und 20000*25000 | Beispiel: Daten pro Punkt 1000 Byte, Punkte: 20000*50000 = 1E9, Arbietsspeicher 500 GByte: Aufteilung in 2 Paritionen mit 20000*25000 und 20000*25000 | ||
= Beispiel für Simulation = | |||
Eine Simulation soll die Temperaturentwicklung bei Sonneneinstrahlung ermitteln. Gegeben sei ein '''Punkt-Oberflächentyp''', der die Beschaffenheit der Oberfläche beschreibt, hier vereinfacht: Straße, Wald, Haus ("street", "wood", "house"). Die Temperaturerhöhung erfolgt in Abhängigkeit des Punkttyps, danach erfolgt ein Temperaturausgleich zwischen den Nachbarpunkten. | |||
Da der Ausgleichsvorgang auf einer Kopie der Daten erfolgen muss (die Nachbarpunkte dürfen sich während der Berechnung nicht ändern!), wird das Modell in der Simulation in Teildaten (hier 1000x1000 Punkte) zerlegt und darauf die Berechnung ausgeführt. Danach werden die Daten wieder ins Gesamtmodell transferiert. | |||
Am berechneten Gesamtmodell wird dann die Durchschnittstemperatur als Aggregation aller Punkte ermittelt. | |||
Die Temperaturverteilung des Gesamtmodells wird in ein Bild mit Breite 2000 Pixel transformiert. | |||
<pre> | |||
# gegebenes Modell laden | |||
model.load(data: "Modell-01"); | |||
# Sicherstellen, dass jeder Punkt ein Attribut "Oberflächentyp" hat. Abbruch der Simulation, wenn nicht. | |||
model.hasAttribute(attributName: "surfacetype"); | |||
# Jeder Punkt bekommt ein Attribut "Temperatur" mit Datentyp Festpunktzahl 16 Bit mit 2 Dezimalstellen) | |||
punkt.addAttribut(attributeName: "temperature", dataType: fixpoint(16,2)); | |||
# Alle Punkte auf 20 Grad setzen: | |||
model.setNumericAttribute(attributeType: "temperature", value: 20.00); | |||
# Definieren einer Funktion für eine Transaktion: die Funktion liefert abhängig vom | |||
# Punktoberflächentyp eine # Temperaturerhöhung: | |||
# Hinweis: Die Funktion muss in C++ definiert werden. | |||
# Die Signatur "Model model, int x, int y" muss verwendet werden. | |||
function(name: "addTemp", body: '''double addTemp(Model model, int x, int y) { | |||
char * surfaceType = model.getAttribute<char*>("surfaceType", line, col); | |||
double rc = model.getAttribute<double>("temperature", line, col); | |||
if (strcmp(surfaceType, "street") == 0){ | |||
rc += 10; | |||
else if (strcmp(surfaceType, "wood") == 0){ | |||
rc += 2; | |||
else if (strcmp(surfaceType, "house") == 0){ | |||
rc += 8; | |||
} | |||
return rc; | |||
}''' | |||
# divideRectangle(): Aufteilung aller Punkte in 1000*1000 Punkte. | |||
# toModel(): Jedes Subquadrat wird als Model behandelt (damit stehen alle Funktionen des Models zur Verfügung). | |||
# transaktion(): Für jeden Punkt des Submodells wird die Transaktion durchgeführt: Funktion addTemp | |||
# neigbourLinearAdaption(): jeder Punkt im Model wird im Attribut "temperature" linear mit den Nachbarpunkten abgeglichen: die Temperatur | |||
# eines Punktes wird aus dem Durchschnitt aller Temperaturen der angrenzenden Punkte berechnet: | |||
# Gewichtung des Punktes: 2, Gewichtung von (4) Kantennachbarn: 1/4=0.25, Gewichtung von (4) Eckpunkten: 1/8=0.125 | |||
# intoModel(): Überführung der Daten des Submodels in das Gesamt-Model. | |||
model.divideRectangle(width: 1000, height: 1000) | |||
.toModel() | |||
.transaktion(function: addTemp) | |||
.neigbourLinearAdaption(attributeName: "temperature", weightPoint: 2, weightEdge: 0.25, weightCorner: 0.125) | |||
.intoModel(); | |||
# | |||
# Durchschnittstemperatur des Gesamtpunktnetzes ermitteln: | |||
model.aggregate(attributeName: "temperature", comment: "Aufheizung der Luft bei Sonnenschein"); | |||
# Temperaturverteilung als Bild erstellen: Farbwechsel bei 20°, 22°...32°, zugeordnete Farben: dunkelblau, ... purpur | |||
model.makePicture(image: "temperature.png", attributeName: "temperature", width: 2000, | |||
values: [20, 22, 24, 26, 28, 30, 32], colors: ["blue-dark", "blue", "blue-light", "red-light", "red", "red-dark", "purple"]); | |||
# Modell unter dem Namen "Modell-02" mit Kommentar speichern: | |||
model.store(data: "Modell-02", comment: "Aufheizung der Luft"); | |||
</pre> |
Aktuelle Version vom 27. November 2021, 15:31 Uhr
Zielsetzung[Bearbeiten]
Simulation in einem Netz mit 10E9 Punkten.
Dies setzt hohe Effizienz voraus, sowohl in Datenhaltung als auch in Programmperformance.
Höchste Effizienz ist nur bei Verarbeitung im Haupspeicher gewährleistet: Bei 100 Takten pro Transaktion (in einem Punkt), 50 Threads und 1 Milliarde Punkte und 2 GHz CPU-Takt ergibt das 1 Sekunde zur Verarbeitung dieser Transaktion über alle Punkte.
Systemaufbau[Bearbeiten]
Es stehen eine Reihe von Grundelementen zur Verfügung, die hocheffizient Daten in den Punkten erzeugen (Modellierung) oder Daten aus den Punkten gewinnen (Aggregation).
Diese Elemente können in einer speziellen Sprache verwendet werden um die Simulation zu beschreiben.
Aus dieser Simulationsbeschreibung wird Quellcode erzeugt, der dann compiliert und abgearbeitet wird.
Aufteilung des Netzes bei zu großen Datenmengen[Bearbeiten]
Passen die Daten aller Punkte nicht in den Arbeitsspeicher, so können die Punkte in Teilgebiete zerlegt werden, die dann in den Arbeitsspeicher passen:
Beispiel: Daten pro Punkt 1000 Byte, Punkte: 20000*50000 = 1E9, Arbietsspeicher 500 GByte: Aufteilung in 2 Paritionen mit 20000*25000 und 20000*25000
Beispiel für Simulation[Bearbeiten]
Eine Simulation soll die Temperaturentwicklung bei Sonneneinstrahlung ermitteln. Gegeben sei ein Punkt-Oberflächentyp, der die Beschaffenheit der Oberfläche beschreibt, hier vereinfacht: Straße, Wald, Haus ("street", "wood", "house"). Die Temperaturerhöhung erfolgt in Abhängigkeit des Punkttyps, danach erfolgt ein Temperaturausgleich zwischen den Nachbarpunkten.
Da der Ausgleichsvorgang auf einer Kopie der Daten erfolgen muss (die Nachbarpunkte dürfen sich während der Berechnung nicht ändern!), wird das Modell in der Simulation in Teildaten (hier 1000x1000 Punkte) zerlegt und darauf die Berechnung ausgeführt. Danach werden die Daten wieder ins Gesamtmodell transferiert.
Am berechneten Gesamtmodell wird dann die Durchschnittstemperatur als Aggregation aller Punkte ermittelt.
Die Temperaturverteilung des Gesamtmodells wird in ein Bild mit Breite 2000 Pixel transformiert.
# gegebenes Modell laden model.load(data: "Modell-01"); # Sicherstellen, dass jeder Punkt ein Attribut "Oberflächentyp" hat. Abbruch der Simulation, wenn nicht. model.hasAttribute(attributName: "surfacetype"); # Jeder Punkt bekommt ein Attribut "Temperatur" mit Datentyp Festpunktzahl 16 Bit mit 2 Dezimalstellen) punkt.addAttribut(attributeName: "temperature", dataType: fixpoint(16,2)); # Alle Punkte auf 20 Grad setzen: model.setNumericAttribute(attributeType: "temperature", value: 20.00); # Definieren einer Funktion für eine Transaktion: die Funktion liefert abhängig vom # Punktoberflächentyp eine # Temperaturerhöhung: # Hinweis: Die Funktion muss in C++ definiert werden. # Die Signatur "Model model, int x, int y" muss verwendet werden. function(name: "addTemp", body: '''double addTemp(Model model, int x, int y) { char * surfaceType = model.getAttribute<char*>("surfaceType", line, col); double rc = model.getAttribute<double>("temperature", line, col); if (strcmp(surfaceType, "street") == 0){ rc += 10; else if (strcmp(surfaceType, "wood") == 0){ rc += 2; else if (strcmp(surfaceType, "house") == 0){ rc += 8; } return rc; }''' # divideRectangle(): Aufteilung aller Punkte in 1000*1000 Punkte. # toModel(): Jedes Subquadrat wird als Model behandelt (damit stehen alle Funktionen des Models zur Verfügung). # transaktion(): Für jeden Punkt des Submodells wird die Transaktion durchgeführt: Funktion addTemp # neigbourLinearAdaption(): jeder Punkt im Model wird im Attribut "temperature" linear mit den Nachbarpunkten abgeglichen: die Temperatur # eines Punktes wird aus dem Durchschnitt aller Temperaturen der angrenzenden Punkte berechnet: # Gewichtung des Punktes: 2, Gewichtung von (4) Kantennachbarn: 1/4=0.25, Gewichtung von (4) Eckpunkten: 1/8=0.125 # intoModel(): Überführung der Daten des Submodels in das Gesamt-Model. model.divideRectangle(width: 1000, height: 1000) .toModel() .transaktion(function: addTemp) .neigbourLinearAdaption(attributeName: "temperature", weightPoint: 2, weightEdge: 0.25, weightCorner: 0.125) .intoModel(); # # Durchschnittstemperatur des Gesamtpunktnetzes ermitteln: model.aggregate(attributeName: "temperature", comment: "Aufheizung der Luft bei Sonnenschein"); # Temperaturverteilung als Bild erstellen: Farbwechsel bei 20°, 22°...32°, zugeordnete Farben: dunkelblau, ... purpur model.makePicture(image: "temperature.png", attributeName: "temperature", width: 2000, values: [20, 22, 24, 26, 28, 30, 32], colors: ["blue-dark", "blue", "blue-light", "red-light", "red", "red-dark", "purple"]); # Modell unter dem Namen "Modell-02" mit Kommentar speichern: model.store(data: "Modell-02", comment: "Aufheizung der Luft");