Xbit-Labs testet Eignung des Semprons als OC-Chip

Original geschrieben von rkinet

Bem: Zuweisung der Aufgaben an einzelne Kerne
Sowas dürften die Compiler fast von alleine auf die Reihe bekommen und die Programmierer sich kaum mit dem Thema beschäftigen müssen. Zudem wird man wohl gleich Multi-Core designs - wie schon beim Dual-Core Intel mit zusätzlich HT - berücksichtigen, bzw. ganze Clusterfelder.

Die Schwierigkeit gute Compiler zu schreiben hat dem Itanium das Leben gekostet, einen Compiler dahin zu trimmen, das er selbst auf zwei Kerne verteilt ist noch um Faktoren schwieriger.

Was eher möglich ist sind Grundkonstrukte, die dazu einladen Multithreaded zu programmieren. Beispiel BeOS:
Wo Fenster und Inhalt des Fensters zwei separate Threads waren, von Haus aus.

Libs, die oft gebrauchte Mechanismen parallel abarbeitet:
z.B. JPEG wo das Bild sowieso viele kleine Quadrate unterteilt ist, dies auf ein paar Kerne zu verteilen ist kein Problem. MP3-libs die sich ein WAV aufbrechen in ein paar Happen und die FFTs parallel drüber laufen lassen.

Und bitte nicht SLI bei Grafik mit Multiprocessing gleichsetzen, da gibt es gewichtige unterschiede, blos weil es sich dort einfach verschachteln lässt, dies gilt aber für Prozessoren nicht im geringsten.

Grüße,
Tom
 
Bin ich jetzt im Kreis der Theoretiker gelandet?!?

@mocad_tom

Du kannst mir glauben, das ich auch schon einige Zeilen Code geschrieben habe(zwar in den seltensten Fällen hart optimierten).

Na also hast du doch in dem Sektor nicht wirklich erfahrung, wenn du noch nie was auf Geschwindigkeit optimieren musstest.


Ein Spiel als Beispiel:
Bei Doom1 glaube ich wurde es eingeführt:
Man hat ein Level designed - danach wurde es in einen "Levelcompiler" geschickt.
Hier wird das Level in einen Baum umgewandelt und dieser ausgeglichen. Dieser Vorgang hat auch mal 2Stunden und länger dauern können (hier wurde eigentlich das Prinzip vom Itanium mal richtig schön umgesetzt - was du in der Compilezeit erledigen kannst, muss nicht in Echtzeit gemacht werden).

Nun hat man einen richtig schönen Datentypen(Baum), richtig schön ausufernd(aber ausgeglichen) und dieser muss im L2-Cache(zumindest das Sichtbare Areal + Puffer) gehalten werden, da in jedem Schleifendurchlauf(Frame) über diesen Baum Kollisionen geprüft werden, bzw. die Geometriedaten via OpenGL an die GraKa weitergericht wurden.

Das ist ja schön und gut, nur nicht allgemein gültig. Einerseits nutzen andere Engines keine zusammenkompilierte Levels, die UT Engines zB. net (das ist auch einfach nicht nötig).

Dann kannst du da trotzdem extrem schlecht die Cache-Belegung ausbalancieren, du hast in deiner Betrachtung nämlich einen kleinen Fehler drinnen - der RAM wird immer gebraucht und es gibt pro Sekunde sehr viele Speicherzugriffe. Der Cache behält wirklich nur die wichtigsten Sachen.

Spiele mit großen Oberflächen-Szenen und sehr viel Weitblick profitieren von großem Cache eben aus diesen Gründen.

Grüße,
Tom


Das ist alles so ziemlich aus der Luft gegriffen! Fang mal an selbst in Assembler zu proggen (natürlich auch performance-krittische Sachen) und schau dir mal die moderne Cache-Verwaltung an. Die ist nämlich auffallend einfach gehalten, ist ja auch nicht möglich für jedes Cache-Byte Kilobytes an Verwaltungsdaten zu speichern.


Ich schweife zwar ab.
Aber noch eine Möglichkeit wie man den zweiten Core für Spiele nutzen kann und besonders viel Realitätsnähe einbringt:
Im zweiten Core kann man z.B. Wasseroberflächen, Gewebesimulation, Haare, Partikeleffekte berechnen lassen. Diese kann man einigermaßen vernünftig abkoppeln und erfordern dennoch einen grossen Brocken an Rechenzeit und bewirken aber einen großen Schritt in Richtung Realität. Dual-Core-Fähigkeiten in Abstraction-Layer zu legen halte für wenig erfolgversprechend.

Grüße,
Tom

Das macht heute die Graka, die ist dafür auch um Längen besser geeignet - die Rechenleistung die die GPU in den Situationen erreicht für die sie gemacht wurde erreichen keine 4 Opterons. Inzwischen ist der Unterschied noch größer geworden, die aktuellen GPUs haben locker 160 Millionen Transistoren Rechenwerk - der Opteron hat ca. 25 Millionen Transistoren Rechenwerk :P.

@rkinet

Da wird nichts doppelt so lang, außer absichtlich herbeigeführt.
Man kann das Laden von absoluten Adressen an den zehn Fingern abzählen, kaum an Bedeutung in der Realität.

Wenn du in deinem Programm extra Pointer nimmst (in C zb sowas: "void main(){int* a;}" dann ist der Pointer a 8 Byte lang. Sowas braucht man doch des öfteren, Puck hat ja mal den Speicherverbrauch von AMD64 vs. IA32 getestet - fast 2mal so viel haben die AMD64 Progs an Speicher gebraucht!

Relative Pointer kannst du nur bei Sprüngen einsetzen, die machen aber nur einen sehr kleinen Teil aus. Der Kompatiblität wegen müssen alle anderen Pointer 8 Byte lang sein.

Natürlich profitieren viele Algorithmen nicht von zusätzlichen Registern, nur bei IA32 ist ja auch die Flexibilität der vorhandenen Register mehr als bescheiden.

Im 32bit PM geht es so halbwegs, richtig schlimm ist nur der RM. 6 Register sind natürlich nicht wirklich viel, aber es gibt eben auf der anderen Seite auch x86 Befehle die dir viel Arbeit abnehmen... manchmal (je nach Vergleichsarchitektur) gehört schon DIV dazu :P.

Die Registerbelegung trifft der Compiler, das ist richtig.

Nur, sowohl DR-DOS/GEM war in C geschrieben, als auch Windows 3.x
Aber für das erste reichte ein 8 MHz 68K Prozessor, beim zweiten lag man erst mit einem 80386SX-25 etwa auf gleicher Geschwindigkeit in einer fast vergleichbar strukturierten Umgebung. Dies zeigt die Kraft einer gut designten CPU.

Du willst das doch wohl nicht wirklich ernsthaft vergleichen?!? (pass auf, was du jetzt sagst ;))

[quote
In der Microkontroller Welt gibt es z.B. den AVR-Risc mit 32 Registern und die Intel 8052 Abkömmlinge. Auch in Assembler und in C ergeben sich drastische Anstiege der Verarbeitungsgeschwindigkeit (200-300%) bei gleichem Netto-Takt und ein Einbruch der Codegröße auf 30-50% trotz ausladener Risc-Struktur.[/quote]

Ja, es gibt auch einen Transmeta Efficeon der im eigentlichen VLIW Modus jede vergleichbar getaktete x86 CPU in Grund und Boden rechnet.

IPC ist zwar schön und gut, aber nur eine Seite der Medallie.

Das Potential von x86-64 ist gewaltig und man wird in wenigen Jahren nur noch den Kopf schütteln über die Primitiv-Lösung x86.
Von Intel wurde IA32 ja nur deshalb weiter geplegt, um IA64 besser an den Markt drücken zu können und möglichst einfach alte 32 Bit Software bei Bedarf auf IA64 laufen zu lassen.

Ok - ich freue mich schon jetzt auf was zum Lachen! Die breite Softwarebasis hat x86 zu dem gemacht was es heute ist, hätte man zB. beim 586er die ISA geändert wäre die x86 Geschichte sicher nicht so glücklich verlaufen.

Außerdem haben es diese IA32 CPUs geschafft zu ihren RISC pendants aufzuschließen - so schlimm kann der IA32 Befehlssatz also nicht sein, im Gegenteil.

Bem: Zuweisung der Aufgaben an einzelne Kerne
Sowas dürften die Compiler fast von alleine auf die Reihe bekommen und die Programmierer sich kaum mit dem Thema beschäftigen müssen. Zudem wird man wohl gleich Multi-Core designs - wie schon beim Dual-Core Intel mit zusätzlich HT - berücksichtigen, bzw. ganze Clusterfelder.

Sowas macht der Compiler nicht im allergeringsten, sowas kann er überhauptnicht! Dafür mus der Progger nämlich erstmal multithreaded programmieren, und das kann oft deinen gesamten Algorithmus völlig umändern.

Ich verweise auf den 1. Satz meines Beitrages... (also sowas müsste man nun aber eigentlich wirklich wissen...).

s. auch http://www.amdzone.com/modules.php?...le&sid=1444
Im Profi-Bereich werden Multi-Core Geräte und z.b. Quadro-SLI bald (Mitte 2005?) kommen.


Da bekomm ich nur einen Fehler. Aber wie gesagt, die Programmierer müssen ein Programm von vornherein auf mehreren Threads aufbauen, sonst bringen mehrere CPUs rein garnix! Rate mal, wieso es heute (bzw. bis zur SMT-Einführung von Inhell) praktisch keine Progs gibt die mehrere CPUs auch wirklich nutzen - es ist einfach ein riesiger Aufwand, den keiner bereit ist zu investieren wenn das betreffende Programm sowieso praktisch ausschließlich auf Single-Systemen laufen wird.
 
Original geschrieben von i_hasser

Dann kannst du da trotzdem extrem schlecht die Cache-Belegung ausbalancieren, du hast in deiner Betrachtung nämlich einen kleinen Fehler drinnen - der RAM wird immer gebraucht und es gibt pro Sekunde sehr viele Speicherzugriffe. Der Cache behält wirklich nur die wichtigsten Sachen.
Die Prediction schmeißt aber nicht vorsorglich Daten raus, sondern es findet nur ein verdrängen von lange nicht benutzten Cache-Zeilen statt.


Das ist alles so ziemlich aus der Luft gegriffen! Fang mal an selbst in Assembler zu proggen (natürlich auch performance-krittische Sachen) und schau dir mal die moderne Cache-Verwaltung an. Die ist nämlich auffallend einfach gehalten, ist ja auch nicht möglich für jedes Cache-Byte Kilobytes an Verwaltungsdaten zu speichern.
siehe Oben, und damit lieferst du gleich die Begründung wie man abschätzen kann, wie Cachelastig ein Programm ist -> mit den Cacheverwaltungsmechanismen im Hinterkopf.
Möchtest du behaupten, das du mehr als 20% deines bisher geproggden Codes auf Performance optimieren musstest/durftest? In useren Projekten ist dafür die Zeit einfach zu knapp bzw. die Prozessoren zu schnell bzw. stellt es mir einfach die Haare zu Berge wenn ich Performance-mäßig schrägen Code sehe und von daher keine nacharbeit mehr leisten muss.

Eng gepackte Datenstrukturen helfen enorm um Cachemisses zu verhindern. Z.B.ist es ein enormer unterschied ob man einen Baum über new-Operatoren, Klassen und durch wirre Traversierung aufbaut, oder ob man sich den Baum schön geordnet über malloc eines grossen Speicherbereichs, simple(weil schnelle)Pointer und Structs zusammenbaut. Wir mussten mal die Datenstruktur für die MMU des MC68irgendwas(020 oder 030) zusammenfrickeln, genau diesen Ansatz konnte ich dann verwenden um für den PocketPC eine schöne Baumstruktur aufzubauen. Mächtig schneller Zugriff auf 20.000 Entries, wobei jeder Entry unkomprimiert 30kb groß war, war die Folge. Konkurrenzprodukte können wir dank des schnellen Zugriffs um längen schlagen. Also werfe mir nicht den Dünnbrettbohrer vor.

Das macht heute die Graka, die ist dafür auch um Längen besser geeignet - die Rechenleistung die die GPU in den Situationen erreicht für die sie gemacht wurde erreichen keine 4 Opterons. Inzwischen ist der Unterschied noch größer geworden, die aktuellen GPUs haben locker 160 Millionen Transistoren Rechenwerk - der Opteron hat ca. 25 Millionen Transistoren Rechenwerk :P.
Das ist momentan möglich mit Shadern:
Shadermodel contest
Klar kann man einfache Routinen den Shadern anvertrauen. Aber was macht man, z. B. wenn man einen Stoff hat, der weht im Wind, mit einem Gegenstand, z. B. ein Stock, dieser stört die Fahne im Wind, die fehlende Kollisionsberechnung muss im Prozessor stattfinden, da hier der Shader schlichtweg überfordert ist.
Nun hat man einen Core brach liegen, für was könnte man den nur einsetzen?
Vielleicht finde ich noch den Artikel über die Kollisionsberechnung von Stoffsimulationen.

Grüße,
Tom
 
Original geschrieben von mocad_tom
Die Prediction schmeißt aber nicht vorsorglich Daten raus, sondern es findet nur ein verdrängen von lange nicht benutzten Cache-Zeilen statt.

Erstens hab ich sowas doch auch nie behauptet, und 2. schmeißt der Hardware Prefetch schon ab und zu mal Daten auf verdacht aus dem Cache ;).

Das Problem sind aber einfach aussehende Funktionen (zB. malloc), die dir den halben Cache leerfegen.

siehe Oben, und damit lieferst du gleich die Begründung wie man abschätzen kann, wie Cachelastig ein Programm ist -> mit den Cacheverwaltungsmechanismen im Hinterkopf.
Möchtest du behaupten, das du mehr als 20% deines bisher geproggden Codes auf Performance optimieren musstest/durftest? In useren Projekten ist dafür die Zeit einfach zu knapp bzw. die Prozessoren zu schnell bzw. stellt es mir einfach die Haare zu Berge wenn ich Performance-mäßig schrägen Code sehe und von daher keine nacharbeit mehr leisten muss.

Also erst sagst du mir wie man auf Cache optimieren kann, und dann sagst du mir, dass du das noch nie gemacht hast. Merkst du was?

Es ist so einfach nicht möglich, weil du als Progger mit einer Hochsprache nie abschätzen kannst, welche Daten noch im Cache liegen müssen und wie sehr die Cache-Verwaltung deinen Vorstellungen folgt (wegen zB. eben Daten die du in deiner Betrachtung nicht berücksichtigen kannst).

Eng gepackte Datenstrukturen helfen enorm um Cachemisses zu verhindern. Z.B.ist es ein enormer unterschied ob man einen Baum über new-Operatoren, Klassen und durch wirre Traversierung aufbaut, oder ob man sich den Baum schön geordnet über malloc eines grossen Speicherbereichs, simple(weil schnelle)Pointer und Structs zusammenbaut. Wir mussten mal die Datenstruktur für die MMU des MC68irgendwas(020 oder 030) zusammenfrickeln, genau diesen Ansatz konnte ich dann verwenden um für den PocketPC eine schöne Baumstruktur aufzubauen. Mächtig schneller Zugriff auf 20.000 Entries, wobei jeder Entry unkomprimiert 30kb groß war, war die Folge. Konkurrenzprodukte können wir dank des schnellen Zugriffs um längen schlagen. Also werfe mir nicht den Dünnbrettbohrer vor.

Mir graut es! new liefert dir genau so einen Pointer wie malloc, nach dem Compiler haben Pointer keinen Unterschied mehr (egal ob nun vorher *void, *int, oder eben *Klasseabc).

Und mal nur so nebenbei, C++ verschlimmert die Sache nochmal um Längen weil die Objektverwaltung auch Ressourcen braucht - bei jedem Objektzugriff.

Und der 68k ist doch wieder was völlig anderes, der ist nicht mal ansatzweise mit einer x86 CPU vergleichbar! Und natürlich ist es einfacher etwas auf low-level Ebene zu schreiben (wenn du eine Berechnung in einem Multiboot Kernel in C verpackst geht das auch noch), aber wenn dir das OS noch dazwischenfunkt hast du einfach ein problem! Ein einfaches malloc sorgt dafür, dass ein recht großer Teil deiner Daten aus dem Cache verschwindet...

Das ist momentan möglich mit Shadern:
Shadermodel contest
Klar kann man einfache Routinen den Shadern anvertrauen. Aber was macht man, z. B. wenn man einen Stoff hat, der weht im Wind, mit einem Gegenstand, z. B. ein Stock, dieser stört die Fahne im Wind, die fehlende Kollisionsberechnung muss im Prozessor stattfinden, da hier der Shader schlichtweg überfordert ist.

Normalerweise berechnet man sowas einfach nicht, weil es viel zu viel Aufwand für nix wäre (überleg mal du hast bei einem Spiel 20 Pelzmonster...). Aber ich sag doch - Kreis der Theoretiker...

Nun hat man einen Core brach liegen, für was könnte man den nur einsetzen?
Vielleicht finde ich noch den Artikel über die Kollisionsberechnung von Stoffsimulationen.

Grüße,
Tom

Bevor man den zu solch sinnlosen Mist einsetzt lässt man ihn lieber brach liegen, der 2. Core könnte zB. den Graka Treiber berechnen (das wäre mal was wirklich sinnvolles), aber dafür müsste der erstmal auf mehrere Threads verteilt werden.


Also wir kommen hier definitiv vom Thema ab, als Programmierer heute kannst du nicht wirklich auf den Cache der CPUs eingehen, fertig! Normalerweise macht man, wenn man doch mal 2 Algorithmen hat oder einen bestimmten Wert den man optimieren könnte einfach einen Test - man lässt den Alg mal mit dem Wert oder mal mit dem anderen Wert durchlaufen und guckt sich an welcher schneller ist - den nimmt man. Mit zielgerichtet auf den Cache optimieren hat das nur leider garnix zu tun, weil da auch noch viele andere Faktoren mit reinspielen.
Manchmal reicht es schon wenn du 2 Anweisungen ein kleines bisschen umformulierst, und dein Alg wird auf einmal 1.5mal so schnell. Das liegt wie gesagt daran, dass du einfach keinen Einfluss auf den Assembler Code hast den der Compiler produziert, und wenn du Assembler richtig optimieren willst musst du dich erstmal durch die tiefen einer CPU wühlen - im Detail betrifft das die Pipelines (bzw. die ungefähren Ausführungszeiten), OOO und Reg Renaming.
Wenn du dir das angeguckt hast kannst du anfangen Assembler zu optimieren - aus der C-Sicht hast du da nach wie vor keine Chance und musst auf Zufälle hoffen (oder du machst dir die Arbeit die sich heute 'dank' 3GHz Boliden eh keiner mehr macht und nimmst inline-Assembler).
 
Original geschrieben von i_hasser

Also erst sagst du mir wie man auf Cache optimieren kann, und dann sagst du mir, dass du das noch nie gemacht hast. Merkst du was?
Ich habe doch ein ganz konkretes Beispiel gebracht, wo ich zumindest auf minimale Speicherzugriffe optimiert habe, es läuft in einem Produktivsystem, die Optimierung war sinnvol, da Ressourcenknappheit des PPCs bestand und wurde dadurch gelöst.


Und mal nur so nebenbei, C++ verschlimmert die Sache nochmal um Längen weil die Objektverwaltung auch Ressourcen braucht - bei jedem Objektzugriff.
Schreibe ich etwas von Objekten? Nein Structs - lese bitte nochmal meine Antwort durch.


Und natürlich ist es einfacher etwas auf low-level Ebene zu schreiben (wenn du eine Berechnung in einem Multiboot Kernel in C verpackst geht das auch noch), aber wenn dir das OS noch dazwischenfunkt hast du einfach ein problem! Ein einfaches malloc sorgt dafür, dass ein recht großer Teil deiner Daten aus dem Cache verschwindet...
Es ist ein anliegen des OS den Speicher nicht zu stark zu fragmentieren, deshalb gibt es auch unterschiedliche (und zum Teil sehr schöne) Speicherzuteilungs-Algos. Ich gehe mal davon aus das ich bei einem malloc eines 2MB großen Speicherbereichs auch nur eine sehr geringe Fragmentierung habe. Und genau in diesen grossen Bereich lege ich den schön taversierten Baum, der als Entries nur Structs hat. Ein EndePointer sagt mir wo ich den nächsten Entry reinlege und erhöhe danach diesen Pointer um sizeof(Struct). Ein Speicherabbild zeigt wie schön geordnet sowas aussehen kann. Sogar mit blosem Auge lässt sich dort die Verpointerung nachvollziehen.

Normalerweise berechnet man sowas einfach nicht, weil es viel zu viel Aufwand für nix wäre (überleg mal du hast bei einem Spiel 20 Pelzmonster...). Aber ich sag doch - Kreis der Theoretiker...
Früher liefen Monster noch als Sprites rum, ein Polygon-Monster war nicht nötig (möglich).
Die nächsten Monster werden zumindest ein bischen Fell haben. Und in 10 Jahren sind Monster ohne Fell undenkbar(soviel zur Felldiskussion :) ). Schau mal die "historie" der computeranimierten Filme durch, dann weiß man was in den nächsten Jahren kommen wird und wieviel Potential da noch drin ist, und nur nicht auf Spiele umgemünzt wird, weil die Kapazitäten nicht da sind.

Bevor man den zu solch sinnlosen Mist einsetzt lässt man ihn lieber brach liegen, der 2. Core könnte zB. den Graka Treiber berechnen (das wäre mal was wirklich sinnvolles), aber dafür müsste der erstmal auf mehrere Threads verteilt werden.
Schlaf dich lieber aus, und überlege dir nochmal eine bessere Antwort.
Das man KI, Kollision, Sound, Game-Controller-Mangament von der Grafikengine weitestgehend trennen kann ist klar. Es wird aber immer noch etwas Rechenzeit des 2. Cores vorhanden sein. Je nachdem wie anspruchsvoll die KI ist sind aber noch 60%Rechenzeit vorhanden. Was wird damit gemacht?

Grüße,
Tom
 
Klettere mal von deinem Elfenbeinturm herunter und schau dich im Land der Realität um ;).

Schlaf dich lieber aus, und überlege dir nochmal eine bessere Antwort.
Das man KI, Kollision, Sound, Game-Controller-Mangament von der Grafikengine weitestgehend trennen kann ist klar. Es wird aber immer noch etwas Rechenzeit des 2. Cores vorhanden sein. Je nachdem wie anspruchsvoll die KI ist sind aber noch 60%Rechenzeit vorhanden. Was wird damit gemacht?

Du hast immernoch nicht erkannt, dass es da zuviele Überschneidungen gibt. Du kannst nicht mal eben den Core die nächsten 50, und den anderen Core die danach kommenden 50 Assembleranweisungen rechnen lassen - da steckt ein viel zu großer Overheat dahinter.

Das Problem von Spielen ist, dass da sehr wenig parallelisierbar ist. Desswegen müsste man für eine Multithreaded Lösung auf sehr viele geteilte Daten zurückgreifen, und das bremst die Geschichte ziemlich weit aus (locked Memory, locked Cache etc.).

Und vor allem kann das nicht der Compiler für dich machen.

Die 60% Rechenzeit liegen dann zB. einfach brach - so ist nunmal die Praxis. Es ist zwar schade, aber es geht nunmal nicht besser.


Ich habe doch ein ganz konkretes Beispiel gebracht, wo ich zumindest auf minimale Speicherzugriffe optimiert habe, es läuft in einem Produktivsystem, die Optimierung war sinnvol, da Ressourcenknappheit des PPCs bestand und wurde dadurch gelöst.

Also mal langsam, was meinst du mit PPC? PocketPC oder PowerPC? (PPC steht für PowerPC, den du wohl kaum meinst... bei einem PowerPC sieht die Cache-Verwaltung in der Praxis dank des anderen Anforderungsbereiches wieder anders aus).

Schreibe ich etwas von Objekten? Nein Structs - lese bitte nochmal meine Antwort durch.

Das ist schon klar. Ein new unterscheidet sich nur praktisch kaum von einem malloc...


Es ist ein anliegen des OS den Speicher nicht zu stark zu fragmentieren, deshalb gibt es auch unterschiedliche (und zum Teil sehr schöne) Speicherzuteilungs-Algos. Ich gehe mal davon aus das ich bei einem malloc eines 2MB großen Speicherbereichs auch nur eine sehr geringe Fragmentierung habe. Und genau in diesen grossen Bereich lege ich den schön taversierten Baum, der als Entries nur Structs hat. Ein EndePointer sagt mir wo ich den nächsten Entry reinlege und erhöhe danach diesen Pointer um sizeof(Struct). Ein Speicherabbild zeigt wie schön geordnet sowas aussehen kann. Sogar mit blosem Auge lässt sich dort die Verpointerung nachvollziehen.

So einfach gesagt ist das falsch. Einerseits gibts die lineare Addresse und andererseits die physikalische, dazwischen steht Paging. Die physikalische Addresse ist sowieso immer recht stark fragmentiert, aber bei x86 beträgt die Pagegröße normalerweise 4kB, wesswegen es da sowieso nix ausmacht.

Und im Bezug auf die lineare Addresse spielt das sowieso keine Rolle ob da was fragmentiert ist oder nicht.


Früher liefen Monster noch als Sprites rum, ein Polygon-Monster war nicht nötig (möglich).
Die nächsten Monster werden zumindest ein bischen Fell haben. Und in 10 Jahren sind Monster ohne Fell undenkbar(soviel zur Felldiskussion :) ). Schau mal die "historie" der computeranimierten Filme durch, dann weiß man was in den nächsten Jahren kommen wird und wieviel Potential da noch drin ist, und nur nicht auf Spiele umgemünzt wird, weil die Kapazitäten nicht da sind.

Du redest dich raus... und Computerfilme sind was gänzlich anderes als 3D Echtzeitgraphik, ersteres wird nämlich ausschließlich von CPUs berechnet, der größeren Flexibilität wegen (man schreibt einmal eine ordentliche Engine die man noch mit Effekten erweitern kann wie es einem Spaß macht, dagegen kannst du eine GPU nicht mal eben um Effekte erweitern).

Ach ja, und heute verlassen die Koordinaten für Fell etc. nichtmal die Graphikkarte. Bis du die mit lächerlichen 256MB/s zurück zur 2. CPU geschickt hast ist die GPU längst wieder 3 Frames weiter.


Und nochmal zu der OS-Frage: Guck dir mal OS/2 Warp3 an, das läuft wie geschmiert auf einem 386-33MHz, bietet viel mehr Features als Win3.1, echtes Multitasking (wo du auch unter 1GHz mehrere Sachen gleichzeitig machen kannst) und braucht im Endeffekt nicht mehr als 4MB Ram. Natürlich kommt OS/2 Warp3 auch mit Win3.11 und DOS Anwendungen zurrecht ;D.

 
Zuletzt bearbeitet:
Da ich schon mal eine MMU und die dazugehörige Adress Translation Table initialisiert habe kannst Du davon ausgehen, das ich den unterschied zwischen physikalischen Adressen und virtuellen Adressen kenne. Um meine Aussage zu konkretisieren - ich hatte einen kaum fragmentierten virtuellen Speicherbereich. Werden nun Cachelines in den Cache geladen wird ein "schöner" Ast des Baums geholt, da sich der Anwender zumeist in diesem Ast bewegt werden hier keine Speicherzugriffe nötig.

Es handelt sich um eine PocketPC-Applikation, sie lief mit dem 208MHz-StrongArm schon Klasse und profitiert von einem 400MHz XScale noch mehr. Diese GHz-Monster sind doch Gift für jeden optimierwütigen Informatiker - Shame on you Mister Ruiz - Shame on you Mister Barret *lol* .
Zum Glück werden keine PocketPCs in Ziegelsteingröße akzeptiert ( wir haben
einen Apple Newton bei uns in der Firma rumliegen - eine sehr viel kleinere App sollte auf dem schon laufen - noch vor meiner Zeit ).

Zum Thema Spiele:
Spiele laufen vereinfacht gesagt in einer großen Schleife. Am Ende der Schleife steht das Zeichnen. Der Synchronisation-Zeitpunkt ist das Zeichnen. Dann müssen beide Cores ihre Threads abgearbeitet haben. Nun hilft die Physik dem Spieleprogrammierer.
*noahnung*
Die Trägheit der Masse - sie verschafft dem Spieleentwickler Zeit.
Es reicht wenn ein Core die Vorarbeit leistet. Die zurechtgerechnete vereinfachte Szene, die in Sachen Physik, KI, Kollision, Multiplayer passt wird zum zweiten Core übergeben und dort ausstaffiert.
Um nun nicht immer einen Kern schlafen zu lassen nimmt man es in kauf zwei Frames in der CPU-Pipe zu haben.
Core1 ist der erste Teil der Pipeline mit simple 3D, KI, Kollision,....
Core2 ist der zweite Teil der Pipeline zuständig für die Übergabe des endgültigen Modells an die Graka, vorher wird aber ausstaffiert.

Nachteil: langsamere Reaktion auf Ereignisse
Allerdings fällt dies nicht ins Gewicht, da man dank 100fps und Trägheit der Massen eine gute Ausrede hat.

Wie ich aber schon mal in einem anderen Thread geschrieben habe wäre ein ausreiffen/ausbalancieren einer solchen Engine auf einer DualCore-Konsole einfacher, da hier nicht sämtliche Konfigurationen im Hinterkopf behalten werden müssen.
Diese Engine würde auf einer SingleCore-Maschine wohl auch laufen, aber mit unnötigem Overhead. Eine Engine die sowohl auf Dual als auch auf Single optimiert ist, ist schon sehr viel Aufwand.
Wann wird es mehr DualCore-Maschinen geben als Single-Core?
Wann wird es die erste richtig schöne Dual-Core-Engine geben?
170%CPU-Ressourcen-Auslastung bei gleichzeitiger Auslastung der Graka.


Grüße,
Tom
 
Original geschrieben von mocad_tom
Da ich schon mal eine MMU und die dazugehörige Adress Translation Table initialisiert habe kannst Du davon ausgehen, das ich den unterschied zwischen physikalischen Adressen und virtuellen Adressen kenne.

Tja, dann willkommen im Club. Bei x86/IA32 hast du übrigens noch eine Ebene darüber, die aber inzwischen keine Bedeutung mehr hat.

Um meine Aussage zu konkretisieren - ich hatte einen kaum fragmentierten virtuellen Speicherbereich. Werden nun Cachelines in den Cache geladen wird ein "schöner" Ast des Baums geholt, da sich der Anwender zumeist in diesem Ast bewegt werden hier keine Speicherzugriffe nötig.

1. Problem ist schonmal das Alignment. Du kannst natürlich selbst dafür sorge tragen, dass der Speicher an einer Page Boundary liegt (sonst ist es Essig mit einer Cache-Line), bei x86 hast du aber allgemein eben noch das Problem, dass jedes CPU Desing eine andere Cache Line Size benutzt - wenn ich mich richtig erinnere sind die beim P4 128 Byte, beim K7/K8 64 Byte (auf jeden Fall benutzt der P4 deutlich größere Cache Lines, worraus auch der größere Bedarf an Speicherbandbreite resultiert).

Und ich hab schonmal gesagt, dass die Sache bei x86 komplizierter ist als bei anderen ISAs, weil bei x86 viel verschiedenere Architekturen am Werkeln sind.

Oft hast du aber auch Algorithmen die sich beim besten Willen nicht auf irgendwelche Cache-Anforderungen optimieren lassen, du bringst hier ein einziges Beispiel an was sich aber nicht verallgemeinern lässt...

Natürlich kann man theoretisch einen Algorithmus konstruieren den man ziemlich genau auf die Cache-Größe einer CPU anpassen kann (wie ich schon gesagt hab, besonders einfach bei welchen die Lookup Tables benutzen), praktisch findest du solche Algorithmen allerdings sehr selten.

Es handelt sich um eine PocketPC-Applikation, sie lief mit dem 208MHz-StrongArm schon Klasse und profitiert von einem 400MHz XScale noch mehr. Diese GHz-Monster sind doch Gift für jeden optimierwütigen Informatiker - Shame on you Mister Ruiz - Shame on you Mister Barret *lol* .
Zum Glück werden keine PocketPCs in Ziegelsteingröße akzeptiert ( wir haben
einen Apple Newton bei uns in der Firma rumliegen - eine sehr viel kleinere App sollte auf dem schon laufen - noch vor meiner Zeit ).

Die einfachste Methode heute was zu optimieren ist per Inline-Assembler. Das hast du zB. bei Prime95, wesswegen das auch leider viel zu gut auf Intel-CPUs läuft.
Prime95 ist aber nicht im geringsten mit einem Spiel vergleichbar, weil der Algorithmus dahinter viel einfacher aufgebaut ist, da gibt es praktisch keine komplexen Zusammenhänge wie bei einem Spiel.


Zum Thema Spiele:
Spiele laufen vereinfacht gesagt in einer großen Schleife. Am Ende der Schleife steht das Zeichnen. Der Synchronisation-Zeitpunkt ist das Zeichnen. Dann müssen beide Cores ihre Threads abgearbeitet haben. Nun hilft die Physik dem Spieleprogrammierer.

Ja, ich weis wie ein Spiel aufgebaut ist ;). Mit DirectX/D3D (6,7,8) *schäm* hab ich schon so einiges programmiert, OpenGL muss ich mir noch angucken.

*noahnung*
Die Trägheit der Masse - sie verschafft dem Spieleentwickler Zeit.
Es reicht wenn ein Core die Vorarbeit leistet. Die zurechtgerechnete vereinfachte Szene, die in Sachen Physik, KI, Kollision, Multiplayer passt wird zum zweiten Core übergeben und dort ausstaffiert.

Ein Core kann nicht vorarbeiten, wie oft denn noch!?!

Es ist einfach nicht möglich einen Core weiterrechnen zu lassen, weil du im Gegensatz zu Prime95 bei einem Spiel noch garnicht weist, was du in der nächsten Sekunde zu berechnen hast!
Und übrigens bieten heutige Grakas auch noch TnL an, was zwar noch nicht soo verbreitet ist, sich aber früher oder später durchsetzen wird. Damit bleiben dann noch mehr Vertexdaten in der Graka und kommen nichtmal mit der CPU in Berührung.

Du denkst dir dauernd neue Beispiele aus um irgendwas zu belegen, was in der Praxis aber einfach nicht so ist!

Um nochmal das Fell-Beispiel zu zerlegen: Heute wird bei sowas wie Fell 1mal ein Haar von der CPU berechnet, das wird zur GPU geschickt und die macht daraus 10'000 oder 100'000 Haare.
An die letztendlichen Vertexdaten kommt die CPU schon wegen der schieren Menge nicht mehr heran, Kollisionsberechnungen sind da (momenten in Echtzeit) völlig unmöglich.


Um nun nicht immer einen Kern schlafen zu lassen nimmt man es in kauf zwei Frames in der CPU-Pipe zu haben.

*lol*

Also was du meinst ist triple Buffering, und das dient nur dazu, dass man den Bildaufbau nicht sieht (lass mal 3D Murks 2000 mit ausgestelltem Double Buffering laufen) und dass der Bildwechsel etwas weicher abläuft.

Ansonsten sind mehrere Bilder in der Pipeline (die übrigens nur in der Graka liegen, bzw. im Graka Ram die dann per Pointer die Addresse von der der RAM-DAC ließt ändert - das nennt sich dann übrigens Page Flipping) tötlich! Bei 3 Bildern und 20fps hast du nämlich eine Verzögerung von 150ms, das kann man schon fast wahrnehmen (ein geübter Ego-Shooter-Spieler der einen CRT hat nimmt das garantiert wahr).

Core1 ist der erste Teil der Pipeline mit simple 3D, KI, Kollision,....
Core2 ist der zweite Teil der Pipeline zuständig für die Übergabe des endgültigen Modells an die Graka, vorher wird aber ausstaffiert.

So ist es ungefähr möglich, nur bekommt der 1. Core dabei praktisch garkeine Arbeit ;).


Nachteil: langsamere Reaktion auf Ereignisse
Allerdings fällt dies nicht ins Gewicht, da man dank 100fps und Trägheit der Massen eine gute Ausrede hat.

Heute hast du selten 100fps, und nicht jeder hat die modernste Graka im Rechner. Wie schon oben gesagt, selbst triple buffering bringt schon merkbare Verzögerungen mit sich.

Wie ich aber schon mal in einem anderen Thread geschrieben habe wäre ein ausreiffen/ausbalancieren einer solchen Engine auf einer DualCore-Konsole einfacher, da hier nicht sämtliche Konfigurationen im Hinterkopf behalten werden müssen.
Diese Engine würde auf einer SingleCore-Maschine wohl auch laufen, aber mit unnötigem Overhead. Eine Engine die sowohl auf Dual als auch auf Single optimiert ist, ist schon sehr viel Aufwand.
Wann wird es mehr DualCore-Maschinen geben als Single-Core?
Wann wird es die erste richtig schöne Dual-Core-Engine geben?
170%CPU-Ressourcen-Auslastung bei gleichzeitiger Auslastung der Graka.

Die Enginge würde bei DualCore so gut wie nix bringen, weil der Overheat der Threadwechsel den Gewinn durch die Auslagerung von so wenig Arbeit auf den anderen Core überwiegt.


Ich hab jetzt keine Lust mehr mir seitenweise einen Kopf zu machen damit du dir wieder nur irgendwelche neue, weit hergeholte Argumente ausdenkst.
 
Mir wird es allmählich auch zuviel.
Andere Pflichten warten, da muss man die Stammtischgespräche wieder zurückstellen

;)

Grüße,
Tom
 
Zum Thema Cache-Ausnutzung in Doom3:

http://www.linuxhardware.org/article.pl?sid=04/10/12/1725246

...The benchmarks below were all performed using “demo1” which ships with Doom 3. The benchmark can be performed by opening the console (Windows: Ctrl+Alt+~; Linux: ~) and typing “timedemo demo1”. All benchmarks were run three times. The first was discarded to allow the caching of the benchmark. The next result was used in the graphs below. The final result was used to verify that there were no anomalies with the previous run. Note: We learned after starting this review that “timedemo demo1 usecache” can be used to remove the need for the initial run. This command will precache the demo for you....
 
Original geschrieben von mocad_tom
Zum Thema Cache-Ausnutzung in Doom3:
Das hat aber nix mit dem CPU-Cache zu tun. Dort macht es wenig Sinn, xx MB Leveldaten und x MB Code in 512 kB L2 schonmal zu precachen :) Es geht nur um die in den Systemen arbeitenden Filecaches u. evtl. auch das Auslagern von Speicher anderer Apps.
 
Original geschrieben von Dresdenboy
Das hat aber nix mit dem CPU-Cache zu tun. Dort macht es wenig Sinn, xx MB Leveldaten und x MB Code in 512 kB L2 schonmal zu precachen :) Es geht nur um die in den Systemen arbeitenden Filecaches u. evtl. auch das Auslagern von Speicher anderer Apps.

Ganz genau so ist es.

Oft wird eine bestimmte Textur erst geladen wenn sie auch wirklich im Level auftaucht - beim 1. Durchlauf würde das die Framerate deutlich in die Knie zwingen, weil die HDD dann normalerweise so um die 100ms lang die Textur laden muss (abhängig von der Größe) - solange 'steht' das Spiel.
 
Das mit usecache war wohl ein Griff ins Klo. Beim Lesen des Artikels hats halt grad gepasst, aber das mit den Texturen is mir dann auch in den Sinn gekommen.
Jetzt muss ich doch noch ein paar Sachen richtig stellen um den begossenen Pudel wieder trocken zu föhnen.

Original geschrieben von i_hasser

Also was du meinst ist triple Buffering, und das dient nur dazu, dass man den Bildaufbau nicht sieht (lass mal 3D Murks 2000 mit ausgestelltem Double Buffering laufen) und dass der Bildwechsel etwas weicher abläuft.
Ansonsten sind mehrere Bilder in der Pipeline (die übrigens nur in der Graka liegen, bzw. im Graka Ram die dann per Pointer die Addresse von der der RAM-DAC ließt ändert - das nennt sich dann übrigens Page Flipping) tötlich!
OpenGL und double Buffering ist mir schon auch ein Begriff, übrigens geht es fast nicht ohne. Angenommen die Applikation würde sofort in den Ausgabepuffer schreiben(zeichnen), dann würde je nach Sortierung zuerst das eine Monster, dann das andere, und dann die Höhle gezeichnet werden. Man zeichnet immer in den Buffer, der gerade nicht angezeigt wird. Am Ende der Zeichen-Callback-Funktion setzt man den Pufferzeiger um. Was du wahrscheinlich meinst ist VSync.


Bei 3 Bildern und 20fps hast du nämlich eine Verzögerung von 150ms, das kann man schon fast wahrnehmen (ein geübter Ego-Shooter-Spieler der einen CRT hat nimmt das garantiert wahr).
Deshalb Spielen die auch mit 800x600 low Detail und die Texturen sind eher in Signalfarben gehalten, Anti-Aliasing und bilineare Filterung aus. Das sind diejenigen, die mir immer die Headshots mit der Pistole verpassen, während ich mit der Uzi auf sie zurenne und Ihnen scheinbar nur durch die Beine schieße. 8)


So ist es ungefähr möglich, nur bekommt der 1. Core dabei praktisch garkeine Arbeit ;).
Das Balancing liegt in der Aufteilung der Details, die simple 3D-Ansicht kann ja schon relativ detailliert sein. Ich weiß nur nicht ob zwei Cores gleichzeitig in einen Framebuffer zeichnen dürfen. Die Übergabe von 3D-Infos von Core zu Core geschieht auf jeden Fall nicht über den Framebuffer. Sondern wieder über einen schönen Struct(mir wäre am liebsten von Cache zu Cache MOESI sei dank :) )


Um nochmal das Fell-Beispiel zu zerlegen: Heute wird bei sowas wie Fell 1mal ein Haar von der CPU berechnet, das wird zur GPU geschickt und die macht daraus 10'000 oder 100'000 Haare.
Genau so habe ich schon mal eine Qualle in OpenGL gemacht. Man nehme einen Spline und mache damit ein Doppel-"S". Nun verzieht man die Kontrolpunkte so, das das Doppel-S schlängelt. Nun wird rotationskörpermäßig gedreht, 12 schlängelnde Doppel-S ergeben eine pumpende Qualle. Bei Haare kann man nicht immer die selbe Locke zig mal Zeichnen. Ausserdem währe dafür dann auch eher ein paar Nurbs geeigneter und unterstützend ein paar Splines. Das Verhalten muss aber auch erst mal physikalisch simuliert/errechnet werden, die Graka kann schon die Nurbs zeichnen, aber wie sind sie ausgeformt? Wo sitzen die Kontrollpunkte, die die Flächen aufspannen, genau dies muss in einem Physikmodell geschehen.


Heute hast du selten 100fps, und nicht jeder hat die modernste Graka im Rechner. Wie schon oben gesagt, selbst triple buffering bringt schon merkbare Verzögerungen mit sich.
Schon die Tests von der SLI GeForce 6600 gelesen, die müssen in der Auflösung und AA schon schön hochschrauben, damit mal die Graka limitiert.

Grüße,
Tom
 
Zuletzt bearbeitet:
Original geschrieben von mocad_tom
OpenGL und double Buffering ist mir schon auch ein Begriff, übrigens geht es fast nicht ohne. Angenommen die Applikation würde sofort in den Ausgabepuffer schreiben(zeichnen), dann würde je nach Sortierung zuerst das eine Monster, dann das andere, und dann die Höhle gezeichnet werden. Man zeichnet immer in den Buffer, der gerade nicht angezeigt wird. Am Ende der Zeichen-Callback-Funktion setzt man den Pufferzeiger um. Was du wahrscheinlich meinst ist VSync.

Autsch!

Also dann hol ich doch mal etwas weiter aus...

Das mit double Buffering hab ich oben schon erklärt, das hast du nur nochmal etwas breitgelatscht.

Früher war es dann üblich das Bild (bzw. das Surface nach DX6 Begriff, den Backbuffer oder wie auch immer) per Blit anzuzeigen. Dabei wird der Puffer Byte für Byte in den sichtbaren Bereich kopiert (von der GPU).

Das ist allerdings etwas langsam und wird nur bei nicht-Vollbild genutzt. Wie du richtig gesagt hast (und wie ich es auch vorher schon richtig gesagt hab...) setzt man heute bei Vollbild einfach den Zeiger wo der RAM-DAC ausließt (wenn du nicht weist was der RAM-DAC ist: der ließt den Bildinhalt aus dem Ram, wandelt ihn in analoge Signale um (bei D-SUB - DAC -> Digital Analog Converter) und schickt es zum Monitor) neu, so dass ein anderes Surface ausgelesen wird.

Das nennt man dann Page Flipping. Das hat mit VSync rein garnix am Hut, VSync lässt sich da aber einfacher implementieren - man flippt die Pages einfach dann wenn der RAM-DAC gerade von unten rechts nach oben links zurückkehrt (das geht jetzt aber am Thema vorbei).

Page Flipping ist natürlich deutlich schneller als wenn die GPU 50mal pro Sekunde ~3MB durch die Gegend kopieren muss.


Also ich weis schon, wovon ich da rede ;).


Deshalb Spielen die auch mit 800x600 low Detail und die Texturen sind eher in Signalfarben gehalten, Anti-Aliasing und bilineare Filterung aus. Das sind diejenigen, die mir immer die Headshots mit der Pistole verpassen, während ich mit der Uzi auf sie zurenne und Ihnen scheinbar nur durch die Beine schieße. 8)

Naja, das ist ein bisschen übertrieben.


Das Balancing liegt in der Aufteilung der Details, die simple 3D-Ansicht kann ja schon relativ detailliert sein. Ich weiß nur nicht ob zwei Cores gleichzeitig in einen Framebuffer zeichnen dürfen. Die Übergabe von 3D-Infos von Core zu Core geschieht auf jeden Fall nicht über den Framebuffer. Sondern wieder über einen schönen Struct(mir wäre am liebsten von Cache zu Cache MOESI sei dank :) )

Nimm dir irgendwann mal ein bisschen Zeit und beschäftige dich mit 3D Graphik (ist nicht böse gemeint).

Heute zeichnet garkeine CPU in den Framebuffer, das macht die GPU - und nur die GPU!

Selbst bei simpler 2D Graphik stellt man inzwischen die GPU etwas anders ein (kein Z-Buffer, keine Perspektivenberechnung, modifizierte Anzeigematrizen (World, View usw. um mal bei DirectX zu bleiben) usw.) und lässt die das zeichnen. Früher gab es dafür einen 2D Beschleuniger.

Und MOESI hat nix, aber auch rein garnix mit dem Programmierer zu tun! MOESI sorgt für die Cache-Kohärenz, der Progger hat aber keinen Einfluss darauf was die CPU eigentlich in den Cache lädt. Er kann der CPU nur den 'Vorschlag' machen das in den Cache zu nehmen, indem er den Bereich prefetcht (siehe MMX Befehle, die CPU kann die Daten aber auch direkt danach wieder aus dem Cache rauswerfen).

Genau so habe ich schon mal eine Qualle in OpenGL gemacht. Man nehme einen Spline und mache damit ein Doppel-"S". Nun verzieht man die Kontrolpunkte so, das das Doppel-S schlängelt. Nun wird rotationskörpermäßig gedreht, 12 schlängelnde Doppel-S ergeben eine pumpende Qualle. Bei Haare kann man nicht immer die selbe Locke zig mal Zeichnen. Ausserdem währe dafür dann auch eher ein paar Nurbs geeigneter und unterstützend ein paar Splines.

Ich sag es dir ein letztes mal: Haare etc. verlassen die GPU heute nicht (ok - der Graka-RAM bekommt sie auch noch zu sehen :P). Schau dir mal Techniken wie Displacement Mapping an (da gabs zB. großes TamTam drum), so ungefähr läuft das auch bei den Haaren ab.

Und mal abgesehen davon... was hat die Qualle bitteschön mit der eigentlichen Problematik zu tun *kopfkratz
Einen Rotationskörper hast du die GPU übrigens sicher nicht berechnen lassen, du hast das eher alles in software rotiert und daraus Vertexdaten abgeleitet und die der GPU gegeben.

Wenn du Zeit hattest hast du die GPU per TnL rotieren lassen.

Schon die Tests von der SLI GeForce 6600 gelesen, die müssen in der Auflösung und AA schon schön hochschrauben, damit mal die Graka limitiert.

Grüße,
Tom [/B]

Mag ja sein, aber mit mehreren Threads kannst du das Problem auch nicht lösen. Die CPU hat heute viel zu rechnen, das lässt sich aber nur sehr sehr schwierig auf mehrere CPUs verteilen.

Außerdem wird TnL heute leider noch sehr zaghaft benutzt, das würde die CPU schon sehr stark entlasten (Doom3 benutzt TnL zB. garnet).
 
@ mocad_tom
Deshalb Spielen die auch mit 800x600 low Detail und die Texturen sind eher in Signalfarben gehalten, Anti-Aliasing und bilineare Filterung aus. Das sind diejenigen, die mir immer die Headshots mit der Pistole verpassen, während ich mit der Uzi auf sie zurenne und Ihnen scheinbar nur durch die Beine schieße
THX für deine vergnüglichen Beiträge ... wusste gar nicht wie lustig das CPU-Forum sein konnte ... ich dachte das war immer was für bierernste spinnerte Geeks *buck* und I_Hasser geht da sogar noch ernsthaft drauf ein ... köstlich ... *chipstüte_leer* *bierhol*

...
 
Original geschrieben von i_hasser

Autsch!
Also dann hol ich doch mal etwas weiter aus...
Okee ich ruder wieder zurück wahrscheinlich sind Begriffe in der Terminologie von VGA-Programmierung, OpenGL und D3D etwas verschieden definiert.



Naja, das ist ein bisschen übertrieben.
Vielleicht sind es mittlerweile 1024x768.
Mir wollte einer klar machen, er spiele nur 640x480 weil dort die Bounding Boxes größer sind und damit die Chance das er andere trifft. *noahnung*


Nimm dir irgendwann mal ein bisschen Zeit und beschäftige dich mit 3D Graphik (ist nicht böse gemeint).
Reicht dir ein Semester OpenGL(in Form eines Seminars, wobei jeder ein Thema beackern musste und dann wurde das vorgetragene ausprogrammiert) und zwei Semester Multimedia, wo wir einen kleinen Raytracer programmiert haben(nicht ausschließlich)? Ausserdem hatte ich die 3Dlive(Zeitschrift nur für Cinema4d 3dsmax Maya usw.), solange bis sie abgesetzt wurde :[ . Also war auch reges Interesse ausserhalb des Studiums vorhanden. Ich wollte mich mal in die CrystalSpaceEngine einarbeiten, war aber zeitlich nicht mehr drin.


Heute zeichnet garkeine CPU in den Framebuffer, das macht die GPU - und nur die GPU!
Ich schreibe das so, damit die werten Mitleser nicht nur Bahnhof verstehen. Wenn ich von zeichnen Schreibe meine ich:
void glVertexPointer(
GLint size,
GLenum type,
GLsizei stride,
const GLvoid *pointer
);
wobei Pointer der Zeiger auf ein Array mit Koordinaten für ein Polygonnetz ist, wenn ich "zeichne" schreibe bitte dies inline reinhängen ;) .


Und MOESI hat nix, aber auch rein garnix mit dem Programmierer zu tun! MOESI sorgt für die Cache-Kohärenz, der Progger hat aber keinen Einfluss darauf was die CPU eigentlich in den Cache lädt. Er kann der CPU nur den 'Vorschlag' machen das in den Cache zu nehmen, indem er den Bereich prefetcht (siehe MMX Befehle, die CPU kann die Daten aber auch direkt danach wieder aus dem Cache rauswerfen).
Zwei Threads teilen sich einen Speicherbereich zum Abgleich.
Core1 arbeitet Thread1 ab
Core2 arbeitet Thread2 ab (wieder mein Pipelinemodell)
Nun arbeitet Core1 fleißig am simplen 3D-Modell. Hält die Szene in einer schön verzeigerten Struktur fest.
Die Struktur muß so beschaffen sein, das Core2 sie schnell mit glVertexPointer an die GPU schicken kann, aber auch bescheid weiß, wo sie noch verschönern muß.
Nun Synczeitpunkt - an dieser Struktur arbeitet nun Core2 weiter.
Wenn nun Core1 nicht allzuviel aus dem Cache rausschmeissen musste, und Core2 auf den Shared Mem zugreifen möchte meldet sich der Snooper von Core1 zu Wort: hey die Cacheline liegt noch bei mir.


Ich sag es dir ein letztes mal: Haare etc. verlassen die GPU heute nicht (ok - der Graka-RAM bekommt sie auch noch zu sehen :P). Schau dir mal Techniken wie Displacement Mapping an (da gabs zB. großes TamTam drum), so ungefähr läuft das auch bei den Haaren ab.
Irgendwo müssen die Kontrollpunkte für die Bezierkurven ja her kommen, die kommen von der CPU. Oder aber man schreibt es in CG(C for Graphics), wobei ich nicht weiß wie mächtig das ist, aber weiter oben habe ich schon einen ShaderContest verlinkt, das schaut noch rel. simpel aus.


Und mal abgesehen davon... was hat die Qualle bitteschön mit der eigentlichen Problematik zu tun *kopfkratz
Einen Rotationskörper hast du die GPU übrigens sicher nicht berechnen lassen, du hast das eher alles in software rotiert und daraus Vertexdaten abgeleitet und die der GPU gegeben.

Wenn du Zeit hattest hast du die GPU per TnL rotieren lassen.

Mit
void glMap1f(
GLenum target,
GLfloat u1,
GLfloat u2,
GLint stride,
GLint order,
const GLfloat *points
);
wobei points ein Zeiger auf ein Array mit den Kontrollpunkten ist. Im einfachsten Fall ein Array aus drei Punkten. Anfangs- und Endpunkt und ein Punkt, der die Kurve beliebig "bauchig" macht. Mit glRotate wird dann um die Rotationsachse gedreht.
Ich wollte anstatt der Qualle den !Haar!kranz vom Homer simulieren, aber dann habe ich mit Nurbs (Wölbungen, Freiflächen) noch einen Rochen gemacht und dann passte das Thematisch nicht mehr in den Vortrag. Also gabs bei meinem OpenGL-Vortrag einen Rochen und eine Qualle, die man durch etwas andere Positionierung und etwas mehr Bezierkurven auch zu einer wallenden, wehenden Mähne machen kann.

Grüße,
Tom
/edit Homer Simpson nicht den aus der griechischen Mythologie
 
Zuletzt bearbeitet:
Original geschrieben von Bokill
@ mocad_tom

THX für deine vergnüglichen Beiträge ... wusste gar nicht wie lustig das CPU-Forum sein konnte ... ich dachte das war immer was für bierernste spinnerte Geeks *buck* und I_Hasser geht da sogar noch ernsthaft drauf ein ... köstlich ... *chipstüte_leer* *bierhol*

...

Im Fernsehen kommt aber auch nur Schrott.
 
MEM_PHYSICAL
Allocates physical memory with read-write access. This value is solely for use with Address Windowing Extensions (AWE) memory.
This value must be used with MEM_RESERVE and no other values.
 
@Bokill

Das Schlimme ist, dass sich so Meinungen verbreiten weder Hand noch Fuß haben.

Genauso wie hier vor einer Weile ein Thread in einem anderen Forum gelinkt war - da behauptete jemand, die AMD CPUs seien wegen der anderen Ausführungszeiten für die Befehle inkompatibel zu Intel CPUs.

Auf den ersten Blick steckt da Technik dahinter, auf den 2. Blick ist es absoluter ...


@Puck

Thema Framebuffer: Wir reden von 3D Graphik. Ja, der VESA Framebuffer von Linux funktioniert ohne GPU, desswegen ist er auch so langsam ;). Der Vorteil ist, dass so ziemlich jede Graka den VESA Standard beherrscht - hat man dann erstmal einen VESA Modi eingeschaltet (es gibt auch viele wo der Framebuffer nur über sog. Bitplanes komplett ansprechbar ist, aber das geht wieder zuweit...) ist man die Graka selbst praktisch los ;).


@mocad_tom

Okee ich ruder wieder zurück wahrscheinlich sind Begriffe in der Terminologie von VGA-Programmierung, OpenGL und D3D etwas verschieden definiert.

Nein, sind sie eigentlich nicht. Es gibt verschiedenste Begriffe für die verschiedensten Sachen, aber Überschneidungen gibt es eigentlich nicht.

Vielleicht sind es mittlerweile 1024x768.
Mir wollte einer klar machen, er spiele nur 640x480 weil dort die Bounding Boxes größer sind und damit die Chance das er andere trifft.

Eigentlich hat die Auflösung da keinen Einfluss drauf, intern (also auf der Spiele-Enginge Ebene) läuft das ja sowieso alles in Floatpoint ab *noahnung*.

Oder meinst du, dass einfach die Pixel größer sind? *buck*

Reicht dir ein Semester OpenGL(in Form eines Seminars, wobei jeder ein Thema beackern musste und dann wurde das vorgetragene ausprogrammiert) und zwei Semester Multimedia, wo wir einen kleinen Raytracer programmiert haben(nicht ausschließlich)? Ausserdem hatte ich die 3Dlive(Zeitschrift nur für Cinema4d 3dsmax Maya usw.), solange bis sie abgesetzt wurde :[ . Also war auch reges Interesse ausserhalb des Studiums vorhanden. Ich wollte mich mal in die CrystalSpaceEngine einarbeiten, war aber zeitlich nicht mehr drin.

Da wird wohl das Problem sein. Es ist genau das selbe Lied wie bei Assembler...

Das klassische Schema, also dass die CPU alle Vertexkoordinaten berechnet, alle Texturen etc. vorgibt und das dann zur GPU schickt gibt es heute nicht mehr (ist wie bei Assembler, normalerweise bekommt man nur 8086 Assembler eingebläut, meckert über die vielen Restriktionen der x86 ISA und merkt erst dann, dass da inzwischen ja eigentlich noch haufenweise Erweiterungen dazugekommen sind).

Schon lange gibt es Techniken wie TnL, mit denen die GPU selbst die Vertexkoordinaten neu berechnet. Und seit 'neuerem' gibt es auch noch Pixel und Vertexshader, sowie deutlich mehr Möglichkeiten TnL in der GPU durchzuführen.

Ein Beispiel was ich vorhin angesprochen hab ist Displacement Mapping (wurde gerade bei der Matrox Parhelia mit Trommeln und Trompeten eingeführt), das verdeutlicht die Sache imho sehr gut - die CPU schickt der GPU eine Heighmap und die GPU errechnet daraus selbstständig Vertexkoordinaten - die kann man dann über eine nicht-ebene Fläche legen, und so zB. ein Gesicht modelieren.

Die anderen Sachen die du angesprochen hast (Raytracer usw.) haben mit den 3D APIs OpenGL, DirectX usw. garnix am Hut. Ein Raytracer funktioniert völlig anders als eine heutige Graka, das gilt auch für darauf aufbauende Programme.

Es gibt schöne Projekte wo versucht wurde mal einen Raytracer für Echtzeitgraphik zu schreiben. Ist imho was nettes rausgekommen, allerdings Leistungsmäßig nicht mit aktuellen Grakas zu vergleichen.


Zwei Threads teilen sich einen Speicherbereich zum Abgleich.
Core1 arbeitet Thread1 ab
Core2 arbeitet Thread2 ab (wieder mein Pipelinemodell)
Nun arbeitet Core1 fleißig am simplen 3D-Modell. Hält die Szene in einer schön verzeigerten Struktur fest.
Die Struktur muß so beschaffen sein, das Core2 sie schnell mit glVertexPointer an die GPU schicken kann, aber auch bescheid weiß, wo sie noch verschönern muß.
Nun Synczeitpunkt - an dieser Struktur arbeitet nun Core2 weiter.
Wenn nun Core1 nicht allzuviel aus dem Cache rausschmeissen musste, und Core2 auf den Shared Mem zugreifen möchte meldet sich der Snooper von Core1 zu Wort: hey die Cacheline liegt noch bei mir.

Core1 hat in der Zeit so ziemlich nix zu tun (hab ich schonmal gesagt...) und du hast ein Problem mit gelocktem Speicher (hab ich glaub ich auch schonmal gesagt, sowas wie ein Scratchpad gibt es bei x86 nicht offiziell).

Und du simplifizierst den ganzen Ablauf viel zu stark. Beispielsweise muss erstmal die komplette KI Berechnung abgelaufen sein - das fehlt bei dir oben völlig. Und sagt dir eigentlich ein Vertex Buffer was? In sowas speichert man normalerweise bei statischen Objekten (also 90% aller Vertices) einmal die Vertexdaten und dann wird das in den GPU Speicher geschickt (und bleibt dort).

Irgendwo müssen die Kontrollpunkte für die Bezierkurven ja her kommen, die kommen von der CPU. Oder aber man schreibt es in CG(C for Graphics), wobei ich nicht weiß wie mächtig das ist, aber weiter oben habe ich schon einen ShaderContest verlinkt, das schaut noch rel. simpel aus.

:]

Nein, das hab ich schon zu oft gesagt...

Die Vertexdaten kommen nicht von der CPU! (jetzt hab ich es ja doch nochmal gesagt :P)

Eine Technik dazu ist zB, dass man der GPU einfach eine Fläche gibt (zB. eine die die Oberfläche von einem Hund beschreibt) und die GPU setzt da selbstständig tausende von Haaren drauf - das Haar selbst gibt man nur 1mal. Man könnte der GPU auch mehrmals verschiedene Haare geben (man erstellt zB. 10 Grundtypen die einander leicht unterscheiden) und so eine größere Vielfalt erreichen.

Mit
void glMap1f(
GLenum target,
GLfloat u1,
GLfloat u2,
GLint stride,
GLint order,
const GLfloat *points
);
wobei points ein Zeiger auf ein Array mit den Kontrollpunkten ist. Im einfachsten Fall ein Array aus drei Punkten. Anfangs- und Endpunkt und ein Punkt, der die Kurve beliebig "bauchig" macht. Mit glRotate wird dann um die Rotationsachse gedreht.
Ich wollte anstatt der Qualle den !Haar!kranz vom Homer simulieren, aber dann habe ich mit Nurbs (Wölbungen, Freiflächen) noch einen Rochen gemacht und dann passte das Thematisch nicht mehr in den Vortrag. Also gabs bei meinem OpenGL-Vortrag einen Rochen und eine Qualle, die man durch etwas andere Positionierung und etwas mehr Bezierkurven auch zu einer wallenden, wehenden Mähne machen kann.

Grüße,
Tom
/edit Homer Simpson nicht den aus der griechischen Mythologie

Thema, wo bist du???


Nochmal zum Thema allokieren von zusammenhängenden virtuellen Adressbereichen:

http://msdn.microsoft.com/library/d...irtualalloc.asp

Im übrigen will ich hier niemanden verkaspern.
Ich stehe zu dem was ich bisher gesagt habe und kann Euch auch noch in die Augen schauen, sollte ich mal einen von Euch persönlich treffen.

Grüße,
Tom

Wie Puck schon sagte, virtueller Speicher hat nix mit physikalischem Speicher zu tun.

Und mal so nebenbei, ich komm mir (trotzdem) langsam verkaspert vor :].

Eine Frage hab ich aber noch: Du hast 2mal auf die MSDN Pages gelinkt... wieso? Was interessieren mich die Speicherreservierungsfunktionen von Windoofs? (mal nebenbei: das 1. läuft auf ein einfaches malloc hinaus, willst du das an einer page boundary haben machst du ein malloc(size+4095) und darauf ein &0xFFFFF000+1<<12, dann hast du den Anfang einer Page erwischt).

Threads können einen bestimmten Speicherbereich gegenseitig freigeben, das ist doch völlig klar. Nur hat damit weder MOESI was zu tun, noch kannst du allgemein davon ausgehen, dass der Speicherbereich im Cache liegt. Als Programmierer siehst du nur RAM. Die CPU ist so ausgelegt, dass sie transparent cached, also so, dass du dich nicht darum kümmern musst (es macht aus Sicht der Funktionalität also keinen Unterschied, ob ein Bereich RAM im Cache liegt oder nicht). Das hat aber leider eben auch zur Folge, dass man mit dem Cache nur extrem schwer rechnen kann, weil die CPU da komplett ihren eigenen Kopf hat.

Also nochmal in der Zusammenfassung (es gab ja mal sowas wie ein Ausgangsthema...):

1. Es ist praktisch extrem schwierig bis unmöglich einen Algorithmus (allgemein) auf einen bestimmten Cache-Bedarf zu optimieren
2. Es ist genauso schwierig ein Spiel für den Betrieb auf mehreren CPUs zu optimieren. Das beweist imho schon das fehlen solcher Spiele trotz Intels SMT.
 
Zuletzt bearbeitet:
Original geschrieben von i_hasser
2. Es ist genauso schwierig ein Spiel für den Betrieb auf mehreren CPUs zu optimieren. Das beweist imho schon das fehlen solcher Spiele trotz Intels SMT.

Sorry, aber hier muß ich dir doch widersprechen. Bei den meisten Spielen ist es prinzipiell soger sehr einfach, auf mehrere Threads zu optimieren. Die Unterteilung in KI, Grafik, Audio, Netzwerk etc. hatten wir schon. Genauso läßt sich bei den meisten Spielen heute die KI noch zerlegen. Bei 1st-person-shootern hast du meistens nicht nur einen Gegner, wo mehrere KIs möglich sind. Genauso hast du häufig noch Mitspieler -> auch mehrere KIs. Das selbe gilt für Strategie-Spiele. Es gibt bei Spielen sehr viele Möglichkeiten für einen multithreaded Ansatz. Das ist zwar nicht gerade einfach, aber die Unterteilung dafür ist ja schon logisch vorgegeben. Spieleentwickler nutzen das nur nicht, weil es mehr Aufwand bedeutet, sie bis jetzt eigentlich nur single-threaded programmiert haben, und sich somit in ein neues Programmiermodell einarbeiten müßten. Auf dem hart umkämpften Spielemarkt, ist für sowas im Moment kein Platz. Das wird aber mit ziemlicher Sicherheit kommen, wenn Leistungssteigerung hauptsächlich mit Parallelität erzielt wird.
 
Original geschrieben von PuckPoltergeist
Sorry, aber hier muß ich dir doch widersprechen. Bei den meisten Spielen ist es prinzipiell soger sehr einfach, auf mehrere Threads zu optimieren. Die Unterteilung in KI, Grafik, Audio, Netzwerk etc. hatten wir schon. Genauso läßt sich bei den meisten Spielen heute die KI noch zerlegen. Bei 1st-person-shootern hast du meistens nicht nur einen Gegner, wo mehrere KIs möglich sind. Genauso hast du häufig noch Mitspieler -> auch mehrere KIs. Das selbe gilt für Strategie-Spiele. Es gibt bei Spielen sehr viele Möglichkeiten für einen multithreaded Ansatz. Das ist zwar nicht gerade einfach, aber die Unterteilung dafür ist ja schon logisch vorgegeben. Spieleentwickler nutzen das nur nicht, weil es mehr Aufwand bedeutet, sie bis jetzt eigentlich nur single-threaded programmiert haben, und sich somit in ein neues Programmiermodell einarbeiten müßten. Auf dem hart umkämpften Spielemarkt, ist für sowas im Moment kein Platz. Das wird aber mit ziemlicher Sicherheit kommen, wenn Leistungssteigerung hauptsächlich mit Parallelität erzielt wird.

Dumm nur, dass die CPU hauptsächlich an der Graphik rechnet...
 
Zurück
Oben Unten