PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Multi Core und kein Weg zurück


Avalox
2005-06-03, 21:12:08
Sah es doch in der guten alten SingleCore Zeit so aus, dass man nur einige Zeit warten brauchte um auch Plattform übergreifend andere System in ordentlicher Performance emulieren zu können. Sprich mit brachialer Rechenleistung diverseste Systeme virtuell Nachbilden zu können.

So ändert sich dieses doch mit den aufkommenden MultiCore Systemen ein wenig. Diese Systeme ziehen ja einen Grossteil ihres Rechenleistungs-Plus aus der Parallelisierung, welche natürlich durch die Software und die Problemformulierung unterstützt werden muss.

Wird es also Software auf heutigen Singlecore Systemen geben, welche also alsbald nicht adäquat auf einem emulierten System betrieben werden kann?

ShadowXX
2005-06-03, 21:16:22
Sah es doch in der guten alten SingleCore Zeit so aus, dass man nur einige Zeit warten brauchte um auch Plattform übergreifend andere System in ordentlicher Performance emulieren zu können. Sprich mit brachialer Rechenleistung diverseste Systeme virtuell Nachbilden zu können.

So ändert sich dieses doch mit den aufkommenden MultiCore Systemen ein wenig. Diese Systeme ziehen ja einen Grossteil ihres Rechenleistungs-Plus aus der Parallelisierung, welche natürlich durch die Software und die Problemformulierung unterstützt werden muss.

Wird es also Software auf heutigen Singlecore Systemen geben, welche also alsbald nicht adäquat auf einem emulierten System betrieben werden kann?

Im Prinzip muss man halt nur auch die Emulatoren an MP anpassen.
Man könnte die verschiedenen Komponenten, die Emuliert werden müssen z.B. auf verschiedene Thread verteilen....(also ein Thread CPU-Emulation, ein Thread GFX-Emulation...)

Das das ganze dadurch nicht einfacher wird in der Programmierung ist natürlich klar.....

Avalox
2005-06-03, 21:21:41
Dieses sind aber sehr enge Grenzen durch das emulierte System gesetzt. Denn letztendlich lässt sich das Problem Emulation einer nicht parallelen Anwendung nicht parallelisieren.

zeckensack
2005-06-03, 21:26:14
Ich verstehe die Fragestellung irgendwie garnicht. Den letzten Satz solltest du nochmal überarbeiten :|

Wenn die Fragestellung vielleicht lauten sollte, ob man, um MT-Systeme zu emulieren, den Emulator ebenfalls multi-threaded aufbauen muss, dann ja. Das ist aber keine wirklich frische Idee. Alle aktuellen Emulatoren die was taugen und nicht völlig performanceunkritisch sind, sind bereits multi-threaded. Sogar Asbach UltraHLE ist multi-threaded (ich zähle hier neun Stück; und es könnten noch mehr sein, von denen ich nur nichts mitkriege).

Ob jetzt C64- oder NES-Emus ST oder MT sind, weiß ich nicht. Ist aber auch relativ latte IMO.

Avalox
2005-06-03, 21:39:35
Es geht mir um die Frage "kann ein Multicore System in jedem Fall ein SingleCore System auf der Aufgaben Ebene ersetzen", dieses an einem konkreten Beispiel.

Es kann es natürlich nicht.

Dass eine Anwendung MT aufgebaut sein muss um überhaupt von einem MultiCore System zu partizipieren ist gegeben, aber der Umkehrschluss, dass auch jede MT Software automatisch von einem MultiCore System profitiert gilt nicht.

ShadowXX
2005-06-03, 22:08:22
Dieses sind aber sehr enge Grenzen durch das emulierte System gesetzt. Denn letztendlich lässt sich das Problem Emulation einer nicht parallelen Anwendung nicht parallelisieren.

Doch...gerade das Problem Emulation.
Du parallelisierst die zu Emulierende Maschine....(du kannst die nicht parallele Anwendung zwar nicht künstlich parallelisieren, aber du kannst die Emulation der TargetMaschine parallelisieren...)

Wie ich schon erwähnt (supereinfaches Beispiel):

Ein Thread Emuliert die CPU&Mem und arbeitet das Programm es zu Emulierenden Rechners ab.

Ein anderer Thread Emuliert den Grafikchip des zu Emulierenden Rechner.

So hat CPU mehr Power für die Emulation des Prozessors als wenn Sie nebenbei sich auch noch um die Grafik kümmern müsste.

Ist eigentlich perfekte Arbeitsteilung und fast wie "geschaffen" für Emulationen.

Avalox
2005-06-03, 22:24:30
Das geht aber nur solange, wie die zu emulierende Maschine getrennte Einheiten hat.

Emulierst du eine Realtime Anwendung hast du davon nicht mal einen Nutzen. Es wird dann parallel gewartet.

Die Idee der Emulation ist doch die Portierung einer Problemlösung auf ein System, welches nicht für die Ausführung gedacht war. Man portiert eine serielle Problemlösung auf ein paralleles System.

Die Anzahl der Cores auf der CPU wird mit quadratischer Geschwindigkeit wachsen.

Die Technik ist an ein Limit angekommen, der Takt ist scheinbar nicht mehr beliebig steigerbar. Da aber die Strukturgrößen mit der heutigen Technik weiter zu verringern sind besteht die einzige Möglichkeit das System zu parallelisieren.

Die Parallelisierung ist und war schon immer eine komplexe und eingeschränkte Notlösung.

Wir erleben grade die Vollendung des ersten Teiles vom Untergang der bekannten Mikroprozessortechnik, etwas übertrieben ausgedrückt. Die Fortsetzung dessen trägt dann den Namen von den nicht mehr verkleinerbaren Strukturgrößen.

Wer wird uns dann retten?

Demirug
2005-06-03, 22:55:55
Bei der Systememulation kann man mit Multiplen Cores wenn diese gut gekoppelt sind durchaus etwas anrichten. Man verteilt die Pipelinestufen des zu emulierenden Systems einfach auf die Cores. Wenn man genügend davon hat kann man auch spekulativ bei Programmverzweigungen einfach mal beide Pfade weiterlaufen lassen.

Avalox
2005-06-03, 23:06:41
Das ist in der Tat ein interessanter Ansatz. Hat was vom Schach spielen.

RoKo
2005-06-04, 10:59:52
Alle aktuellen Emulatoren die was taugen und nicht völlig performanceunkritisch sind, sind bereits multi-threaded.
Huch, was bringt das denn bei denen?
Man verteilt die Pipelinestufen des zu emulierenden Systems einfach auf die Cores.
Huch, jetzt reden wir aber nicht mehr über die Art von Emulatoren, die so im Netz rumschwirren um alte Software laufen zu lassen, oder?

Demirug
2005-06-04, 11:18:42
Huch, jetzt reden wir aber nicht mehr über die Art von Emulatoren, die so im Netz rumschwirren um alte Software laufen zu lassen, oder?

Im Prinzip schon wenn diese Emulatoren auch noch alternative Hardware (hauptsächlich die CPU) emulieren müssen. Fängt man allerdings an auf diese Art Emulatoren zu schreiben muss man sich mit vielen Problemen rumschlagen die bisher nur CPU Designer kannten.

RoKo
2005-06-04, 11:51:19
Im Prinzip schon wenn diese Emulatoren auch noch alternative Hardware (hauptsächlich die CPU) emulieren müssen. Fängt man allerdings an auf diese Art Emulatoren zu schreiben muss man sich mit vielen Problemen rumschlagen die bisher nur CPU Designer kannten.
Kann mir nicht vorstellen, dass das klappt, man müsste doch nach fast jeder Instruktion die Threads synchronisieren. Gerade bei einem DynaRec dürfte das nach meiner Vorstellung weit mehr Leistung weghauen als es einbringt.

Demirug
2005-06-04, 12:12:40
Kann mir nicht vorstellen, dass das klappt, man müsste doch nach fast jeder Instruktion die Threads synchronisieren. Gerade bei einem DynaRec dürfte das nach meiner Vorstellung weit mehr Leistung weghauen als es einbringt.

Ich schrieb ja das man gut gekoppelte Cores für so etwas braucht und ja man synchronisert sehr häufig allerdings auf einem Mikrolevel welcher die Aufwendig Syncronisations Objekte umgeht. Es geht ja im Wesentlichen nur darum wenige Daten von einem Core zum nächsten zu schicken.

In der gesamt Betrachtung verbraucht dieser Ansatz natürlich mehr Rechenleistung als die klasischen Lösungen. Es geht ihr ja auch mehr darum wie man die sonst ungenutzte Leistung der zusätzlichen Cores dennoch einsetzten kann.

DynaRec ist dabei ja wiederum eine andere Geschichte. Hier könnte man die zusätzlichen Cores so nutzen das jeder eine andere Strategie analysiert und die erfolgversprechendeste dann zur Ausführung gebracht wird.

Wie schon geschrieben ist das jetzt aber alles sehr stark auf Emulatoren bezogen und stellt damit ein Sonderfall des "Problem" Multicore da.

zeckensack
2005-06-04, 13:00:57
Huch, was bringt das denn bei denen?Sinnvolle Lastverteilung.
Die zu emulierenden Systeme bestehen ja zumeist aus mehreren parallel arbeitenden Elementen. Damit meine ich jetzt nicht Threads, sondern Chips. Also wie schon gesagt: CPU, Sound, Grafik, Massenspeicher, Eingabegeräte-Controller etc.
Die können auf dem "echten" System alle gleichzeitig arbeiten, von daher ist es sinnvoll sie in Threads zu modellieren.

RoKo
2005-06-04, 13:47:39
DynaRec ist dabei ja wiederum eine andere Geschichte. Hier könnte man die zusätzlichen Cores so nutzen das jeder eine andere Strategie analysiert und die erfolgversprechendeste dann zur Ausführung gebracht wird.
Wenn irgendwie von Geschwindigkeit bzw. "ordentlicher Performance" die Rede ist, betrachte ich nur DynaRecs. Auf die Weise könnte man aber wirklich ein wenig rausholen.
Aber ich denke auch mit den tollsten Optimierungen bleibt es dabei, dass die Zeitspanne zwischen dem Erscheinungsdatum eines neuen Systems und der Möglichkeit einer ausreichend schnellen Emulation des selbigen sich vergrößern wird.

Wie schon geschrieben ist das jetzt aber alles sehr stark auf Emulatoren bezogen und stellt damit ein Sonderfall des "Problem" Multicore da.
Nicht nur sehr stark, der Thread handelt allein von Emulatoren, oder ;)

Die können auf dem "echten" System alle gleichzeitig arbeiten, von daher ist es sinnvoll sie in Threads zu modellieren.
Aber nur wenn der Emulator am Ende auch auf einem MultiCPU/Core-System läuft, oder? Womit es aktuell noch unbedeutend wäre.
Ältere Emus sind übrigens singlethreaded, das Timing ist dort viel zu kritisch (man müßte nach jedem Pixel synchronisieren, da man die Farbpaletten während des Bildaufbaus ändern kann). Selbst MultiCore-Systeme werden singlethreaded emuliert - siehe http://www.aarongiles.com/mamemem/part6.html

Demirug
2005-06-04, 14:22:31
Wenn irgendwie von Geschwindigkeit bzw. "ordentlicher Performance" die Rede ist, betrachte ich nur DynaRecs. Auf die Weise könnte man aber wirklich ein wenig rausholen.
Aber ich denke auch mit den tollsten Optimierungen bleibt es dabei, dass die Zeitspanne zwischen dem Erscheinungsdatum eines neuen Systems und der Möglichkeit einer ausreichend schnellen Emulation des selbigen sich vergrößern wird.

Die Zeitspanne von Original zur Emulation ist im wesentlichen Abhängig von der Zusammen der zur Verfügung stehenden Rechenleistung.

Bisher war die Zuname der Rechenleistung eher eine lineare Sache. Durch Multicore kann diese aber nun viel schneller wachsen.

Natürlich wird es am Anfang etwas dauern bis die Entwickler und die Tools soweit sind davon wirklich gebrauch zu machen. Wenn man aber einmal über diese Hürde hinweg ist wird man das mehr an Rechenleistung gut nutzen können.

Ein typische Problem bei Emulationen sind Speicher Read/Writes bei komplexen Memorymaps. Hier kann man hervoragend Multicore nutzen. Während sich ein Core darum kümmert das der aktuelle Befehl abgearbeitet wird kümmert sich ein zweiter um den Speicherzugriff. In vielen Fällen enthält nicht jeder CPU Befehl einen Speicherzugriff so das die Abarbeitung des Befehlscodes nicht mehr zwingend warten muss bis der Letzte Speicherzugriif erledigt ist. Falls notwendig kann ich dazu auch ein Beispiel bauen.

RoKo
2005-06-04, 14:46:20
Bisher war die Zuname der Rechenleistung eher eine lineare Sache. Durch Multicore kann diese aber nun viel schneller wachsen.
Aber die Zunahme der Rechenleistung pro Core wird sinken. Ist eben die Frage, was am Ende mehr ausmacht.
Wobei sich die Situation schnell wieder ändern kann, wenn andere Systeme noch mehr Richtung MultiCore gehen als PCs bzw. das System auf dem man seine Emus laufen lassen will.
Ein typische Problem bei Emulationen sind Speicher Read/Writes bei komplexen Memorymaps. Hier kann man hervoragend Multicore nutzen. Während sich ein Core darum kümmert das der aktuelle Befehl abgearbeitet wird kümmert sich ein zweiter um den Speicherzugriff. In vielen Fällen enthält nicht jeder CPU Befehl einen Speicherzugriff so das die Abarbeitung des Befehlscodes nicht mehr zwingend warten muss bis der Letzte Speicherzugriif erledigt ist. Falls notwendig kann ich dazu auch ein Beispiel bauen.
Naja, die Problematik kommt aber bei zum Beispiel Konsolen nicht zum tragen. Qemu nutzt meines Wissens sogar die eigene MMU irgendwie dafür. PearPC hat ein echtes Problem damit, man will sich da aber wohl künftig auch an Qemu orientieren.

Demirug
2005-06-04, 15:08:47
Aber die Zunahme der Rechenleistung pro Core wird sinken. Ist eben die Frage, was am Ende mehr ausmacht.
Wobei sich die Situation schnell wieder ändern kann, wenn andere Systeme noch mehr Richtung MultiCore gehen als PCs bzw. das System auf dem man seine Emus laufen lassen will.

Mit jedem neuen Core den ein Prozessor bekommt steigt die verfügbare Recheneleistung aber gleich um ein gewaltiges Stück.

Naja, die Problematik kommt aber bei zum Beispiel Konsolen nicht zum tragen. Qemu nutzt meines Wissens sogar die eigene MMU irgendwie dafür. PearPC hat ein echtes Problem damit, man will sich da aber wohl künftig auch an Qemu orientieren.

Die MMU eines Prozessors kann man nur missbrauchen wenn man das System komplett übernimmt. Sobald man nur Gast in einem anderen System ist hat man keinen Zugriff mehr auf die MMU. Zudem haben viele Systeme wie auch ein PC Memory Mapped IO. In solchen Fällen steht hinter einer Speicheraddresse kein einfacher Datenspeicher sondern letzten Endes eine Logik. Wenn man diese aufgrund fehlenden Hardware ebenfalls emulieren muss kommt man um eine Software MMU überhaupt nicht herum.

RoKo
2005-06-04, 15:18:58
Mit jedem neuen Core den ein Prozessor bekommt steigt die verfügbare Recheneleistung aber gleich um ein gewaltiges Stück.
Die für einen Emulator nutzbare Leistung aber um ein weniger gewaltiges Stück.
Die MMU eines Prozessors kann man nur missbrauchen wenn man das System komplett übernimmt.
Zumindest unter Linux geht es wohl mit Einschränkungen auch so, siehe http://fabrice.bellard.free.fr/qemu/qemu-tech.html#SEC17
Wobei ich mich gerade frage - diese Virtualisierungserweiterungen, die Intel und AMD bringen wollen, würden diese genau da helfen?

Demirug
2005-06-04, 15:33:20
Die für einen Emulator nutzbare Leistung aber um ein weniger gewaltiges Stück.

Wenn die Emulation entsprechend zerlegt ist schon.

Zumindest unter Linux geht es wohl mit Einschränkungen auch so, siehe http://fabrice.bellard.free.fr/qemu/qemu-tech.html#SEC17

Dieser "Trick" funktioniert auch unter Windows. Allerdings würde ich nicht darauf bauen da mit einiger Wahrscheinlichkeit der Addressraum den man haben will schon belegt ist. Zudem ist es notwendig das die Speicherarchitektur des zu emulierenden Systems möglichst ähnlich ist.

Wobei ich mich gerade frage - diese Virtualisierungserweiterungen, die Intel und AMD bringen wollen, würden diese genau da helfen?

Das kann insofern helfen das man seine Emulation auf einem tieferen Level aussetzt. Gleichzeitig hat man dann jedoch auch keinerlei Basisfunktionen eines OS mehrs. Gerade im PC Umfeld mit der vielen Unterschiedlichen Hardware wird sich IMHO keiner drauf einlassen auf diesem Level einen Systememulator zu bauen.

RoKo
2005-06-04, 16:07:03
Wenn die Emulation entsprechend zerlegt ist schon.
Wenn man sie nicht mehr weiter zerlegen kann nicht ;) Bei einer exponentiellen Steigerung der Coreanzahl hat man diesen Punkt schnell erreicht, egal wie gut man den Emu letztlich zerlegen kann.
Dieser "Trick" funktioniert auch unter Windows. Allerdings würde ich nicht darauf bauen da mit einiger Wahrscheinlichkeit der Addressraum den man haben will schon belegt ist. Zudem ist es notwendig das die Speicherarchitektur des zu emulierenden Systems möglichst ähnlich ist.
Scheint für Qemu jedenfalls ganz nützlich zu sein.
Was sind das denn für Geräte, bei denen die Speicherarchitektur weniger ähnlich ist?
Das kann insofern helfen das man seine Emulation auf einem tieferen Level aussetzt. Gleichzeitig hat man dann jedoch auch keinerlei Basisfunktionen eines OS mehrs. Gerade im PC Umfeld mit der vielen Unterschiedlichen Hardware wird sich IMHO keiner drauf einlassen auf diesem Level einen Systememulator zu bauen.
Stimmt, Treiber, schade. Immerhin gibt es doch einen Emulator, der sowas macht (Amithlon). Aber genau an besagtem Problem hapert es bei diesem jetzt immer mehr.

zeckensack
2005-06-04, 16:21:20
Aber nur wenn der Emulator am Ende auch auf einem MultiCPU/Core-System läuft, oder? Womit es aktuell noch unbedeutend wäre.Jein.
Von vernünftiger Thread-Programmierung profitieren auch Single-CPU-Systeme. ZB ist es nicht wirklich erforderlich, dass ein C64-Emulator permanent 100% CPU-Last erzeugt, nur um gleichzeitig die Emulation zu fahren und auf Menükommandos reagieren zu können. Ich will jetzt nicht wirklich die ganze Begründung dafür bringen (Roman ahoi), aber das geht mit mindestens zwei Threads viel leichter und eleganter als nur mit einem. Dadurch steigt natürlich nicht die Performance der Applikation, aber das Zusammenspiel mit dem Restsystem ist besser, weil "gutmütiger".

Schaden tut's jedenfalls nicht. Win32 ist zwar fürchterlich ineffizient (und blöd) im Umgang mit Threads, aber mit guter Planung dürfte der Verlust <=1% bleiben. Ich habe weiland beim Umstieg von ST auf MT in der ersten Ausprobier-Phase 10% verloren, mittlerweile ist der Unterschied wie gesagt <=1%.
Ältere Emus sind übrigens singlethreaded, das Timing ist dort viel zu kritisch (man müßte nach jedem Pixel synchronisieren, da man die Farbpaletten während des Bildaufbaus ändern kann).Das glaube ich nicht, Tim. Paradebeispiel "state machine". Da muss man garnichts nach jedem Pixel.
Selbst MultiCore-Systeme werden singlethreaded emuliert - siehe http://www.aarongiles.com/mamemem/part6.htmlNiemand braucht dringender Threads als der ;)

Demirug
2005-06-04, 16:41:46
Schaden tut's jedenfalls nicht. Win32 ist zwar fürchterlich ineffizient (und blöd) im Umgang mit Threads, aber mit guter Planung dürfte der Verlust <=1% bleiben. Ich habe weiland beim Umstieg von ST auf MT in der ersten Ausprobier-Phase 10% verloren, mittlerweile ist der Unterschied wie gesagt <=1%.

Da muss ich doch gleich mal Fragen was Linux (oder was auch immer dein Bezugspunkt ist) da besser macht?

Primär hat man mit dem OS ja nur zwei Berürungspunkte. Den Threadsheduler und die Frage wie fein die Looks im Kern granuliert sind. Den Rest hat man ja selbst in der Hand.

RoKo
2005-06-05, 00:07:34
Von vernünftiger Thread-Programmierung profitieren auch Single-CPU-Systeme. ZB ist es nicht wirklich erforderlich, dass ein C64-Emulator permanent 100% CPU-Last erzeugt, nur um gleichzeitig die Emulation zu fahren und auf Menükommandos reagieren zu können.
Das geht auch SingleThreaded problemlos - zumindest in einem Emu, da der ja eh über eine Art Scheduler läuft.
Aber egal, ich hatte eh nur die eigentliche Emulation im Sinn. Klar, dass MultiThreading für die GUI praktisch ist.
Ich habe weiland beim Umstieg von ST auf MT in der ersten Ausprobier-Phase 10% verloren, mittlerweile ist der Unterschied wie gesagt <=1%.
In Deinem Glide-Wrapper? Ich habe da ein ähnliches Dingen und auch vor, es auf (optionalen) MultiThreading-Betrieb umzustellen, da es da einfach prima passt. Aber so gut passt es nicht überall, denke ich.
Das glaube ich nicht, Tim. Paradebeispiel "state machine". Da muss man garnichts nach jedem Pixel.
Jop, aber das erhöht den Implementierungsaufwand und hört sich für mich nach einem doch deutlich spürbaren Performanznachteil auf SingleCore-Systemen an. Ergo unwahrscheinlich dass solche Emus das gemacht haben. Hätte ich auch noch nicht gesehen.
Niemand braucht dringender Threads als der ;)
Glaube nicht, er müsste selbige wohl übel oft synchronisieren.

zeckensack
2005-06-05, 00:32:31
Da muss ich doch gleich mal Fragen was Linux (oder was auch immer dein Bezugspunkt ist) da besser macht?Ich vergleiche schon auf dem selben OS, aber (wie üblich) insbesondere die Kommunikation zwischen Threads. Wenn er erstmal läuft, dann läuft er, klar, damit habe ich auch kein Problem.

Zwei Sachen, die ich neulich ausprobiert habe:
PostThreadMessage+GetMessage(NULL) (keine Fenster)
vs
Nix+if (nix_da) Sleep(1)
Sender links, Empfänger rechts. Sonstiger Synchronisationsaufwand (Critical Section zum updaten des Status des Kommunikationspuffers, Event setzen wenn Puffer leer etc) kommt noch dazu, ist aber bei beiden gleich.

Beides funktioniert gleich gut. Nur Variante 2 ist mindestens 20 mal so schnell (single-CPU, kein SMT).

Demirug
2005-06-05, 08:24:00
Wie kommt man den auf die Idee mit GetMessage Threads zu syncroniseren?
Das ist doch völlig offensichtlich das man dabei eine Menge Overhead hat für die Dinge die man gar nicht braucht.

Wobei ich den Sleep da durchaus auch etwas kritisch sehe. Du kannst es dir leisten im schlimmsten Fall 16 ms (ok eigentlich 15, irgendwas) auf die Abarbeitung der Jobs zu warten?

Hast du das MT System auch auf Singelcore-CPUs aktiv oder war das nur zum testen. Gerade wenn man lediglich ein 2 Thread System hat kann man das eigentlich auch so aufbauen das es auf Singlecore CPUs nur mit einem Thread läuft.

zeckensack
2005-06-05, 16:46:52
Wie kommt man den auf die Idee mit GetMessage Threads zu syncroniseren?
Das ist doch völlig offensichtlich das man dabei eine Menge Overhead hat für die Dinge die man gar nicht braucht.Wenn Windows nicht so blöd wäre, würde ich das auch nicht machen.
Es gibt aber keine andere sinnvolle Möglichkeit, den Scheduler dazu zu veranlassen, den Empfänger-Thread laufen zu lassen, sobald der Sender-Thread auf dessen Ergebnisse warten muss (oder der FIFO voll ist).
Genau genommen synchronisiere ich die Threads nicht damit. Ich zwinge den Scheduler auf die Weise nur dazu, den Backend-Thread schön regelmäßig laufen zu lassen, sobald Arbeit zu verrichten ist.
Ich möchte ja alles so asynchron wie möglich haben, und synchronisiere daher nur (mit einem Event), wenn der Sender mal ein Ergebnis vom Empfänger zurückholen muss.

Sleep(n) schaltet auf einen zufällig ausgewählten Thread wenn einer mit mindestens gleich hoher Priorität "ready" ist. Wenn der Sender eine höhere Priorität hat als der Empfänger -- was einem bei Lib-Programmierung durchaus passieren kann, ohne dass man was dagegen tun könnte -- dann beobachtet man folgendes//da schreibt der andere Thread sein Ergebnis rein, wenn er so weit ist
volatile int handshake=-1;
//!!blockiere die CPU für 20ms mit 100% Last!!
while (handshake==-1) Sleep(0);
"Sleep returns immediately."

Yield() schaltet ebenfalls auf einen zufällig ausgewählten Thread um. Duh. Und ist auf Win9x nicht verfügbar.

Die Fibre-API wiederum ist so hirngeschädigt (IsFiber()? -- schön wär's, aber die Funktion existiert nicht!), dass man sie praktisch nicht verwenden kann.


Du kannst natürlich auch sowas machen:
//Sender
while (was_auch_immer)
{
while (fifo.zu_voll||braucht_ergebnis) WaitForSingleObject(fifo.leer_event,1);
//Kommando in den FIFO schmeißen
//<...>
SetEvent(fifo.mindestens_eins_ist_drin);
}

//Empfänger
while (nicht_beendet)
{
if (fifo.platz==fifo.kapazität)
{
SetEvent(fifo.leer_event);
WaitForSingleObject(fifo.mindestens_eins_ist_drin);
}
//Kommando holen, ausführen
//<...>
}

Das ist allerdings noch beschissener. Habe ich alles schon versucht. Und zwar liegt das daran, dass der Scheduler immer sofort beim Setzen des Events jeweils auf den anderen Thread wechselt. Ergo maximal ein Kommando im FIFO, und damit überhaupt kein asynchrones Verhalten mehr. Threadwechsel schafft ein 2GHz K8 etwa 800k pro Sekunde. Total sinnlos.

Ergo: Win32 ohne weitere Hilfsmittel, viel Erfahrung und reichlich schmutzige Tricks ist für MT-Programmierung schlicht ungeeignet. Und das liegt nicht an schlechter Implementation. Nein. Das funktioniert alles exakt so, wie es in der MSDN-Doku "spezifiziert" wird. Das Design des Systems ist einfach so verkorkst.

Und bei Gelegenheit können wir uns mal über Threads, Prozesse, Message Queues, Fenster, und deren Verhältnisse zueinander unterhalten.
*grummel*
Aber das ist hier doch ziemlich OT.

Wobei ich den Sleep da durchaus auch etwas kritisch sehe. Du kannst es dir leisten im schlimmsten Fall 16 ms (ok eigentlich 15, irgendwas) auf die Abarbeitung der Jobs zu warten?Geschlafen wird natürlich nur, wenn ich festgestellt habe dass der aktuelle Thread nichts sinnvolles zu tun hat. Beim Backend-Thread bedeutet das dass der Kommando-FIFO leer ist.
Aber ja, das kann ich mir leisten. WaitForSingleObject ist zwar einerseits eine sehr zuverlässige Methode, den Kontextwechsel zu veranlassen, aber wie bereits ausgeführt totales Gift für den Durchsatz. Ich hatte mit Sleep(0) kaum Probleme. Nur bei Programmen die die (meiner Meinung nach dringend zu entfernenden) Prioritäts-Funktionen von Win32 nutzen. Warum das so ist, steht weiter oben.
Hast du das MT System auch auf Singelcore-CPUs aktiv oder war das nur zum testen. Gerade wenn man lediglich ein 2 Thread System hat kann man das eigentlich auch so aufbauen das es auf Singlecore CPUs nur mit einem Thread läuft.Das MT-System ist optional und konfigurierbar, wird aber für viele Dinge zwingend benötigt, weil es einen Schutzschild zwischen OpenGL (thread-safe) und Client-Code, mit unkontrollierbarer Anzahl und Nutzung von Threads, darstellt.

Demirug
2005-06-05, 17:38:58
Zeckensack, schon mal APCs bzw. WaitableTimer versucht?

zeckensack
2005-06-05, 18:44:52
Zeckensack, schon mal APCs <...>"When a user-mode APC is queued, the thread to which it is queued is not directed to call the APC function unless it is in an alertable state."
Q (http://msdn.microsoft.com/library/en-us/dllproc/base/asynchronous_procedure_calls.asp)
<...> bzw. WaitableTimer versucht?
"If the timer is set before the thread enters an alertable wait state, the APC is canceled."
Q (http://msdn.microsoft.com/library/en-us/dllproc/base/setwaitabletimer.asp)

"Alertable state" bedeutet in beiden Fällen, dass das Backend schlafen muss. Keine Asynchronität => keine Ausnutzung von MP/SMT-Maschinen.

Das ist das Problem dass sich durch die gesamte Thread-Synchronisation von Win32 zieht. Um auf jedwede Inter-Thread-Kommunikation korrekt zu reagieren, muss der Thread sich erst schlafen legen. Wenn er schläft, kann er nicht arbeiten. Wenn er am Ende seiner Zeitscheibe noch gearbeitet hat, funktioniert der Scheduler nicht mehr.
Du kannst entweder schlechten Durchsatz auf MP-Systemen oder schlechten Durchsatz auf SP-Systemen, oder beides haben. Vernünftigen Durchsatz auf allen Maschinen bekommst du so nicht hin.

Demirug
2005-06-05, 20:00:29
Du bist ein harter brocken. ;)

Ich denke aber jetzt das ich dein Problem verstanden habe.

Dein Workerthread der die für OpenGL bestimmten Jobs dispatcht soll immer nur dann laufen wenn es auch Jobs gibt. Dabei soll er sich die Rechenzeit gerecht mit dem Hauptthread der Anwendung teilen. Also beide Threads sollen ihere Quotas voll ausnutzen. Gibt es keine Jobs mehr zu dispatchen soll der Workerthread sich schlafen legen und eigentlich erst dann wieder arbeiten wenn es wieder etwas in der Liste gibt. Dein Problem ist aber nun das die Syncronisationsobjekte von Windows die Eigenschaft haben das sie die CPU sofort dem Thread der gewartet hat zuweisen wenn ein anderer Thread die Sync auslösst. Du möchtest aber viel lieber das der Hauptthread seine Zeit voll ausnutzt und dabei die Jobliste wieder füllen kann. Dann soll der Workerthread diese wieder leerräumen und falls er damit fertig ist bevor die Zeit angelaufen ist die CPU wieder freigibt.

Soweit richtig?

zeckensack
2005-06-05, 20:47:30
Genau.

Btw,
der Backend-Thread macht nicht ausschließlich OpenGL-Dispatch, sondern erledigt auch die gesamte Ressourcenverwaltung, kümmert sich um den Render-State, berechnet diverse Dinge (Mipmaps zB), und übernimmt auf Wunsch noch das Fenster-Handling und die dazugehörige Message-Pumpe.
Insbesondere letzteres schreit geradezu nach GetMessage als primären Einstiegspunkt für die Kommunikation.

Demirug
2005-06-05, 22:19:48
OK, wenn du auch den MessagePump in dem Thread hast funktioniert das was ich dir Vorschlagen wollte nicht.

Im Prinzip muss man den Thread nämlich nur mit Suspend schlafen legen sobald der letzte Job erledigt ist und dann wieder mit Resume aufwecken sobald es wieder etwas zu tun gibt. Resume hat nämlich den Vorteil das es den Thread nur wieder in die Liste der aktiven Threads setzt aber nicht sofort mit der Ausführung beginnt.

Aufgrund des Messageloops kannst du aber den Thread nicht komplett blocken.