Multithreading, volatile, Cache usw.



  • knivil schrieb:

    Ja, das ist auch klar. Aber das hat doch auch nichts mit dem Problem hier zu tun.

    Doch. der wie willst du entscheiden, wie viel Cache ein Prozess benutzen darf?

    Wieso denn eigentlich Prozess?
    Wir reden doch über Prozessoren und ihre L1 Caches.

    Aber das ist auch interessant.
    Kann man einem Prozess einen bestimmten Teil vom Cache zuordnen?



  • jenz schrieb:

    Bei getrennten Caches brauche ich doch ein cache kohärenz protokoll, also ein verfahren dass über die caches hinweg die gleichen daten in die caches schreibt.

    wenn jeder prozessor aber gleich in allen bzw in dem einen großen cache lesen kann, dann braucht man das eben nicht.

    Des gilt nur für L3, weil shared! und ist im Hintergrund! Und das "Protokoll" ist schneller als ein RAM Zugriff!



  • Du brauchst immer ein Protokoll wenn mehrere Einheiten auf einen gemeinsamen Speicher zugreifen. http://de.wikipedia.org/wiki/Arbiter . Das gleiche Problem tritt ja auch auf, wenn mehrere DMA-Engines auf den RAM zugreifen.

    Wieso denn eigentlich Prozess?

    Einem Prozessor, der nichts macht, ist es egal ob er einen getrennten Cache benutzt oder nicht.



  • jenz schrieb:

    knivil schrieb:

    Ja, das ist auch klar. Aber das hat doch auch nichts mit dem Problem hier zu tun.

    Doch. der wie willst du entscheiden, wie viel Cache ein Prozess benutzen darf?

    Wieso denn eigentlich Prozess?
    Wir reden doch über Prozessoren und ihre L1 Caches.

    Aber das ist auch interessant.
    Kann man einem Prozess einen bestimmten Teil vom Cache zuordnen?

    Er meint Prozessor, aber das lässt sich über Heuristiken lösen. Hitrates, oder letzte Zugriffszeit



  • jenz schrieb:

    Und was ich eben noch nicht verstehe:
    Warum sollte der gleichzeitige parallele Zugriff auf einen gemeinsamen Cache so problematisch sein? Also rein vom Prinzip her stelle ich mir dir Frage.

    Klar wird der Cache immer dicker, wenn er mehr Leitungen hat, aber das ist doch kein prinzipielles Problem.

    Für nur lesen wäre das vielleicht noch denkbar (aber eher nicht, siehe weiter unten).

    Aber wie willst du in so einen Cache schreiben?

    Jeder "gute" Cache ist "multi-way associative", d.h. jede RAM Adresse kann an verschiedenen Stellen im Cache liegen. D.h. es gibt hier gewisse Registerbänke die "Verwaltungsdaten" enthalten. Es wird z.B. auch vermerkt wann eine Cache-Line das letzte mal verwendet wurde, damit entschieden werden kann welche Lines rausfliegen wenn neue Daten dazukommen.
    Um also einen neuen Wert in den Cache zu tun muss man erstmal folgendes machen:
    * In allen Cache-Lines die in Frage kommen nachgucken wie alt sie sind
    * Die älteste ermitteln
    * Diese Cache-Line ggf. in den Speicher (oder darunterliegenden Cache) zurückschreiben
    * Die neuen Daten in die Cache-Line stecken
    * Den "letzer Zugriff" Wert aktualisieren

    Wie soll das funktionieren wenn das 2 Cores gleichzeitig machen sollen?

    Und nochmal zurück zum "nur gleichzeitig lesen, und nur einer darf schreiben" Gedankenexperiment: wie willst du das alles synchronisieren, so dass während ein Cache-Update im Gange ist, die lesenden Cores nicht Mist lesen?

    Und zwar so synchronisieren, dass alles 100% gleich schnell bleibt?

    Zeig mir eine CPU mit shared L1 Cache, und ich zeig dir eine CPU die Performance verschenkt.



  • PhilippHToner schrieb:

    Ja doch, du kommst mit deinem tollen SharedCache her aber dass der ganze Müll auch in Registern ist, ist dir Wurst? Willst du jetzt mit SharedRegistern arbeiten 😃

    Man PhillipHToner,

    es geht um die Konsistenz zwischen den L1 Caches...

    Die Register sind mal längst völlig uninteressant.



  • jenz schrieb:

    es geht um die Konsistenz zwischen den L1 Caches...
    Die Register sind mal längst völlig uninteressant.

    Mein NOT-Shared L1 Cache braucht gar nix bzgl. Konsistenz und wenn doch, dann kümmert sich dass OS darum, weil ich in meinem Programm explizit ein Mutex locke.

    Dein Shared L1 Cache hat mein geschildertes Problem!!



  • hier drin scheint es genau darum zu gehen:

    http://www.springerlink.com/content/mx6683v800477x13/

    collective cache

    such ich mal nach



  • BTW: die Konsistenz zwischen den Caches ist auch kein eigentliches Problem, da gibt es schöne Lösungen die gut funktionieren und vor allem auch ohne extrem viel Performance zu kosten. z.B. MESI

    http://en.wikipedia.org/wiki/MESI_protocol



  • PhilippHToner schrieb:

    jenz schrieb:

    es geht um die Konsistenz zwischen den L1 Caches...
    Die Register sind mal längst völlig uninteressant.

    Mein NOT-Shared L1 Cache braucht gar nix bzgl. Konsistenz und wenn doch, dann kümmert sich dass OS darum, weil ich in meinem Programm explizit ein Mutex locke.

    Dein Shared L1 Cache hat mein geschildertes Problem!!

    ich glaube, dass hier ist ein guter Anfang für dich:
    http://de.wikipedia.org/wiki/Cache-Kohärenz



  • hustbaer schrieb:

    BTW: die Konsistenz zwischen den Caches ist auch kein eigentliches Problem, da gibt es schöne Lösungen die gut funktionieren und vor allem auch ohne extrem viel Performance zu kosten. z.B. MESI

    http://en.wikipedia.org/wiki/MESI_protocol

    Ja, ich glaube ja auch, dass es so, wie es ist eine sehr gute Lösung ist.
    Also das getrennte L1/L2 und gemeinsame L3 Caches (Intel) gut funktionieren.

    Aber ich frage mich, ob es prinzipiell besser ist L1(/L2) zu trennen.

    Jetzt lese ich noch mal einen anderen Post.
    Danke für deine Gedanken.



  • Ich verstehe nicht warum du immer auf "prinzipiell" rumreitest.

    Es ist ein praktisches Problem - und mir zumindest reicht es vollkommen aus, wenn man etwas praktisch nicht lösen kann. Ich meine es bringt mir auch nix wenn ich weiss dass man Schach prinzipiell komplett durchrechnen kann. Mit der Info könnte ich genau nix anfangen, weil es praktisch eben trotzdem unmöglich ist.



  • hustbaer schrieb:

    Jeder "gute" Cache ist "multi-way associative", d.h. jede RAM Adresse kann an verschiedenen Stellen im Cache liegen. D.h. es gibt hier gewisse Registerbänke die "Verwaltungsdaten" enthalten. Es wird z.B. auch vermerkt wann eine Cache-Line das letzte mal verwendet wurde, damit entschieden werden kann welche Lines rausfliegen wenn neue Daten dazukommen.
    Um also einen neuen Wert in den Cache zu tun muss man erstmal folgendes machen:
    * In allen Cache-Lines die in Frage kommen nachgucken wie alt sie sind
    * Die älteste ermitteln
    * Diese Cache-Line ggf. in den Speicher (oder darunterliegenden Cache) zurückschreiben
    * Die neuen Daten in die Cache-Line stecken
    * Den "letzer Zugriff" Wert aktualisieren

    Wie soll das funktionieren wenn das 2 Cores gleichzeitig machen sollen?

    Deswegen stelle ich mir das so vor, dass von Anfang an klar ist, dass Prozessor 1 die Cachelines 1-9 und Prozessor 2 die Lines 10-19 usw. verwaltet.

    Das Lesen aus "fremden" cachelines würde ich "optimitisch" machen, also einfach draufloslesen. wenn die cacheline dann rausgeschmissen wird, dann wird der lesevorgang ab dann ungültig und muss wiederholt werden.



  • jenz schrieb:

    hier drin scheint es genau darum zu gehen:

    http://www.springerlink.com/content/mx6683v800477x13/

    collective cache

    such ich mal nach

    Kauf dir des Buch. Deine Lösung konvergiert einfach zur dazu, dass es langsamere aber mehrere Prozessoren gibt, die irgendwie an der Northbridge ein shared memory haben, welches schneller ist als RAM und trotzdem werden sie nach wie vor einen NOT-Shared L1 cache machen, weil es einfach Sachen gibt, die keine anderen Prozessor interessieren, also wieso teuer im shared memory abspeichern! Du kannst gerne noch 20 Hierarchien um die bestehende bauen, aber die schnellsten Einheiten werden niemals Shared sein!

    Ich habe mir auch schon Hierarchien durchgelesen, die baumstrukturartig immer N Prozessoren mit einem SharedCache versehen. Wenn Prozessor dann was von woanders braucht, muss der richtige Weg durch den Baum-Graphen gefunden werden. Das sind alles Sachen, die vielleicht kommen, aber dann haben diese Dinger immernoch ein NOT-Shared L1 Memory oder wie es dann genannt wird!



  • jenz schrieb:

    Das Lesen aus "fremden" cachelines würde ich "optimitisch" machen, also einfach draufloslesen. wenn die cacheline dann rausgeschmissen wird, dann wird der lesevorgang ab dann ungültig und muss wiederholt werden.

    Und wie bekommt die lesende CPU mit wenn die schreibende CPU gerade was schreibt während die lesende liest?
    Und die lesende dadurch Schrott gelesen hat?

    Also woher weiss die dann dass es Schrott war?



  • hustbaer schrieb:

    jenz schrieb:

    Das Lesen aus "fremden" cachelines würde ich "optimitisch" machen, also einfach draufloslesen. wenn die cacheline dann rausgeschmissen wird, dann wird der lesevorgang ab dann ungültig und muss wiederholt werden.

    Und wie bekommt die lesende CPU mit wenn die schreibende CPU gerade was schreibt während die lesende liest?
    Und die lesende dadurch Schrott gelesen hat?

    Also woher weiss die dann dass es Schrott war?

    Weil sich die "ID" der Line geändert hat.
    Dafür reicht dann auch ein Bit.



  • Naja die ID könnte aber zufällig noch gepasst haben - kann ja alles mögliche rauskommen, auch was was teilweise stimmt.
    Der Leser müsste schon 2x lesen oder so, um zu checken dass da was nicht passt.

    OK, irgendwie liesse sich das vielleicht noch hinbiegen, aber einfach stell ich es mir nicht vor.



  • hustbaer schrieb:

    Naja die ID könnte aber zufällig noch gepasst haben - kann ja alles mögliche rauskommen, auch was was teilweise stimmt.
    Der Leser müsste schon 2x lesen oder so, um zu checken dass da was nicht passt.

    OK, irgendwie liesse sich das vielleicht noch hinbiegen, aber einfach stell ich es mir nicht vor.

    Er bräuchte nur das eine Bit zweimal lesen, einmal bevor er liest und einmal wenn er fertig ist. Das ergebniss wäre dann ein Cachemiss, also auch ganz "normal".

    Das Bit bräuchte auch immer nur zwischen 1 und 0 wechseln. Dabei gehe ich davon aus, dass das ersetzen einer Line wesentlich länger dauert als das Lesen eines Wertes.

    Also Ablauf:
    - line suchen
    -> möglicher cachemiss wenn nicht gefunden
    - line gültig?
    -> möglicher cachemiss wenn nicht ungültig
    - line bit speichern
    - wert aus line auslesen
    - line bit mit gespeichertem vergleichen
    -> möglicher cachemiss, wenn bit wert gewechselt hat.
    und das hier muss vielleicht auch noch mal gemacht werden:
    - line gültig?
    -> möglicher cachemiss wenn nicht ungültig



  • jenz schrieb:

    Er bräuchte nur das eine Bit zweimal lesen, einmal bevor er liest und einmal wenn er fertig ist. Das ergebniss wäre dann ein Cachemiss, also auch ganz "normal".

    Und was wenn während dem lesen 2 schreib-operationen waren? das bit sich also 2 mal geändert hat und beim 2. lesen wieder auf dem ursprungswert steht?



  • Shade Of Mine schrieb:

    jenz schrieb:

    Er bräuchte nur das eine Bit zweimal lesen, einmal bevor er liest und einmal wenn er fertig ist. Das ergebniss wäre dann ein Cachemiss, also auch ganz "normal".

    Und was wenn während dem lesen 2 schreib-operationen waren? das bit sich also 2 mal geändert hat und beim 2. lesen wieder auf dem ursprungswert steht?

    Ja, stimmt. Ich bin einfach mal davon ausgegangen, dass Lesen schneller ist als Schreiben.

    Wenn das falsch ist, dann hilft vielleicht nur ein (2-Bit?)-Counter


Anmelden zum Antworten