Bug in Windows (10) gefunden?
-
Martin Richter schrieb:
Deine Funktion heißt LOCK! Es ist kein Lock ...
Man kann mit einem Autoreset-Event ein Lock realisieren. Das funktioniert dann genauso wie eine CRITICAL_SECTION, nur nicht so effizient (die CRITICIAL_SECTION lockt für den Fall das beide nicht überschneidend locken wollen im Userland durch eine atomare Operation).
Intern benutzt CRITICAL_SECTION auch ein Event für den Fall, dass überschneidend auf den kritischen Abschnitt zugegriffen wird.
Daher ist die Bezeichnung *Lock*AndReleaseThread hier voll angebracht.Deinen MVP hast Du sicher nicht durch Erkenntnisse im Multithreading bekommen.
-
Sieht so aus, als würde Windows die Threads die nur auf ein Ereignis warten bevorzugen, und die die auf mehrere warten kommen nicht zum Zuge. Ich finde das ist ein Bug.
Mehr als ein herzhaftes LOL hat das eigentlich nicht verdient.
-
hustbaer schrieb:
Mehr als ein herzhaftes LOL hat das eigentlich nicht verdient.
Was intelligentes hast Du wohl nicht zu sagen.
-
Bonita.M schrieb:
Man kann mit einem Autoreset-Event ein Lock realisieren.
ja
Bonita.M schrieb:
Das funktioniert dann genauso wie eine CRITICAL_SECTION, [...]
nö
Bonita.M schrieb:
Intern benutzt CRITICAL_SECTION auch ein Event für den Fall, dass überschneidend auf den kritischen Abschnitt zugegriffen wird.
nö
-
dot schrieb:
Bonita.M schrieb:
Man kann mit einem Autoreset-Event ein Lock realisieren.
ja
Bonita.M schrieb:
Das funktioniert dann genauso wie eine CRITICAL_SECTION, [...]
nö
Bonita.M schrieb:
Intern benutzt CRITICAL_SECTION auch ein Event für den Fall, dass überschneidend auf den kritischen Abschnitt zugegriffen wird.
nö
Was bist Du denn für ein Schwachkopf?
Wenn ich in einem Thread auf einem Autoreset-Event WairForSingleObject( hEvt, INFINTE ) sage und später wieder SetEvent( hEvt ), dann ist das die gleiche Funktion wie bei einer CRITICAL_SECTION, nur nicht so effizient.
Und guck doch mal in den Header in dem CRITICAL_SECTION definiert ist. Da siehst du dann ein HANDLE für ein Event. Ich hab EnterCriticalSection und LeaveCriticalSection mal disassembliert, und MS macht da genau das was andere auch machen, nämlich mit eeinm Lock-Flag arbeiten das atomar geändeert wird, und für den Contention-Fall wird auf die Kernel-Betriebsmittel in beschriebener Art und Weise zugegriffen.
Ich habe in meinem ersten Posting die Implementation einer effizienten Condition-Variable verlinkt. Darin steckt auch ein Mutex bzw eine Critical Section. Und da mache ich genau das selbe wie EnterCriticalSection und LeaveCriticalSection, nur einen Tick effizienter.
Selten so einen ignoranten Dummkopf gelesen wie dich.
-
Ich halte es da mit Mr.Flounder:
The Best Synchronization Is No Synchronization
http://www.flounder.com/no_synchronization.htm
Ansonsten geht mir die Diskussion etwas auf den Keks.
-
Bonita.M schrieb:
Was bist Du denn für ein Schwachkopf?
lol, na wenn dir eh alles klar ist, wieso verschwendest du hier dann deine Zeit damit, so Schwachköpfe wie uns Dinge zu fragen, auf die eh nur du allein die Antwort kennst?
Bonita.M schrieb:
Und guck doch mal in den Header in dem CRITICAL_SECTION definiert ist. Da siehst du dann ein HANDLE für ein Event. Ich hab EnterCriticalSection und LeaveCriticalSection mal disassembliert [...]
Meine Windows Header sind wohl leider völlig veraltet, vielleicht kannst du mir den aktuellen mal schicken? Und was für einen tollen Disassembler du da hast! Meiner zeigt mir leider die ganzen Event Syscalls irgendwie nicht an, vermutlich kann der in Sections, die in Paralleluniversen liegen, nicht rein...
Bonita.M schrieb:
Ich habe in meinem ersten Posting die Implementation einer effizienten Condition-Variable verlinkt.
Ja, die ist ja offenbar so wahnsinnig effizient, dass sie schon gar nicht mehr korrekt ist, manch ein Thread flutscht da ja durch als wär er nie drangekommen; nur die Performance is dafür halt nicht so toll und Systemressourcen verschwendet sie auch, aber darum geht's ja nicht; ich wünschte, so Schwachköpfe wie ich könnten sich auch mal sowas geniales einfallen lassen...
Das ist jedenfalls definitiv ein Bug in Windows 10 (damals auf XP war das ja alles noch besser); die Windows Kernel Entwickler sind halt auch nur unwesentlich weniger schwachköpfig als wir alle hier. Aber es kann halt nicht jeder soviel von paralleler Programmierung verstehen wie du, wir machen das ja nur beruflich...
-
Kannst dich ja immernoch als "Conchita Wurscht" anmelden. Du Held du.
Ja, jetzt werde ich etwas stänkerig, nachdem ich mir das Alles angesehen habe.
Wenn ich admin wäre würde sofort deine komplette IP Class B Range rausfliegen.
-
Bonita.M schrieb:
hustbaer schrieb:
Mehr als ein herzhaftes LOL hat das eigentlich nicht verdient.
Was intelligentes hast Du wohl nicht zu sagen.
Nicht jemandem der so austeilt wie du. Ausserdem will ich ja nicht dein Weltbild erschüttern.
Wenn du meinst eine effiziente CV Implementierung zu haben, dann lass sehen. Als Klasse mit den üblichen Funktionen, so dass man sinnvoll darüber argumentieren kann. Und wenns geht vielleicht ohne Komma-Operator oder sonstigen unüblichen Konstrukten.
Und was deine Behauptung dass das von dir beobachtete Verhalten ein Fehler sein soll angeht... naja die ist erstmal wirklich einfach nur lachhaft. Da müsste schon ein Link zu ner Doku dabei sein wo bezüglich "Fairness" beim Aufwecken der wartenden Threads irgendwas garantiert wird. Oder wenigstens nicht-garantiertes aber aktuell implementiertes Verhalten beschrieben wird.
Hast du sowas, dann lass sehen.Ich kenne nur das Gegenteil. z.B. wo Microsoft unmisverständlich dokumentiert dass Dinge wie CRITICAL_SECTIONs nicht "fair" sind. Siehe
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682608(v=vs.85).aspx
Der Satz der mit "There is no guarantee" anfängt.
Hat jetzt mitWaitForSingleObject/WaitForMultipleObjects
nix zu tun, aber wie gesagt nur ein Beispiel - ich bin ja hier nicht in der Bringschuld.
-
Wenn du meinst eine effiziente CV Implementierung zu haben, dann lass sehen. Als Klasse mit den üblichen Funktionen, so dass man sinnvoll darüber argumentieren kann. Und wenns geht vielleicht ohne Komma-Operator oder sonstigen unüblichen Konstrukten.
Ich habe die Implementierung in meinem ersten Posting verlinkt. Und gg. den Komma-Operator ist meiner Meinung nach nichts einzuwenden.
Und was deine Behauptung dass das von dir beobachtete Verhalten ein Fehler sein soll angeht... naja die ist erstmal wirklich einfach nur lachhaft. Da müsste schon ein Link zu ner Doku dabei sein wo bezüglich "Fairness" beim Aufwecken der wartenden Threads irgendwas garantiert wird.
Aufgabe eines Multitasking-Betriebssystems ist es, Rechnezeit gleichmäßig zu verteilen (zumindest unter gleich priorisierten Threads). Microsoft hat sogar versucht genau das versucht zu realisieren. Ich habe mal LockAndReleaseThread geändert, dass es eine alphabetische Thread-ID ausgibt:
char GetID(); DWORD WINAPI LockAndReleaseThread( LPVOID lpvThreadParam ) { for( ; ; ) { WaitForSingleObject( ::hEvt, INFINITE ); printf( "spawned thread with id %c is holding lock\n", (char)GetID() ); if( !::fReleased ) ReleaseSemaphore( ::hSema, 1, NULL ), ::fReleased = true; Sleep( 100 ); SetEvent( ::hEvt ); } return 0; } char GetID() { static std::unordered_map<DWORD, char> mapTIDsToIDs; static char nextId = 'A'; DWORD dwThreadId; if( mapTIDsToIDs.find( dwThreadId = GetCurrentThreadId() ) == mapTIDsToIDs.end() ) return mapTIDsToIDs[dwThreadId] = nextId++; else return mapTIDsToIDs[dwThreadId]; }
Und siehe da, wenn Du NTHREADS auf 10 setzt, dann kommen die LockAndReleaseThreads reihum, immer in der selben Reihenfolge, CPU-Zeit.
Dass der Hauptthread *nie* CPU_Zeit bekommt, ist ein konzeptueller Fehler vom Windows-Kernel.
Wenn es nach deiner Lesart ging, dann wär es sogar o.k., wenn ein Thread immer wieder das Event bekomen würde und kein anderer Thread schedult würde.Ich kenne nur das Gegenteil. z.B. wo Microsoft unmisverständlich dokumentiert dass Dinge wie CRITICAL_SECTIONs nicht "fair" sind.
Bei der CRITICAL_SECTION ist das was anderes, denn die synchronisiert für den Fall, dass keine Contention vorliegt im Userland. Das kann man nicht fair implemtieren, will man effizient bleiben.
-
löschen
-
Bonita.M schrieb:
Dass der Hauptthread *nie* CPU_Zeit bekommt, ist ein konzeptueller Fehler vom Windows-Kernel.
Nö, ist ein konzeptioneller Fehler in deiner Verwendung des Windows Kernels.
Aber ist auch sinnlos, hier weiter zu diskutieren, sowohl Windows als auch Standard C++ an sich kommen mit einer fertig implementierten Condition Variable, die nicht nur viel effizienter, sondern vor allem auch korrekt ist...
-
Der wollte doch nur ein bischen Lob, dass er der erste und einzige ist dem bis jetzt dieser unglaubliche Bug in Win10 aufgefallen ist. Und was macht ihr, anstelle ihn zu huligen, gibts Erklärungen zum Verhalten. Und dafür hat er sich nun gestern angemeldet. Echt 'ne Schande so mit einem neuen Forenmitglied umzuspringen.
Also vom mir bekommst du ein dickes Lob, nicht nur für den tollen Bug, sondern auch für dein vorbildliches Benehmen.
-
Erstens bin ich kein "der", sondern eine "die".
Und zweitens ging es mir darum, eine Lösung zu finden. Die ist mir aber selbst eingefallen (siehe vorangegangener Artikel mit dem Workaround). Alles weitere war unnützes Rauschen.
-
Bonita.M schrieb:
Erstens bin ich kein "der", sondern eine "die".
Unverschämt und anmaßend bist du so oder so.
-
Wieder der beste Beweis das Frauen dumm sind.
-
var schrieb:
Wieder der beste Beweis das Frauen dumm sind.
Du Affe kannst doch nichtmal richtig Deutsch.
Wenn, dann hieße das ", da*ss* Frauen dumm sind.".
Also wer ist hier wohl dumm?
-
@Martin Richter: Einmal schreibst du "Ein AutoReset Event ist kein Lock!" und einmal "Ein AutoReset event ist ein Lock."
-
dot schrieb:
Aber ist auch sinnlos, hier weiter zu diskutieren, sowohl Windows als auch Standard C++ an sich kommen mit einer fertig implementierten Condition Variable, die nicht nur viel effizienter, sondern vor allem auch korrekt ist...
Condition-Variablen werden in Producer-Consumer-Verhältnissen eingesetzt. Dabei wied das Lock nur ganz kurz gehalten und die Verarbeitung dessen was man aus der Queue geholt hat ist entweder lang weil man CPU-Zeit eines anderen Kerns nutzen wollte, oder weil man einen blockenden Aufruf tätigt. Letztlich kommt es in der Praxis daher nie zu dem Szenario, dass *immer* irgendein Thread auf das innewohnende Mutex wartet, so dass jemand der auf die Signalisierung der CV wartet aushungert. Daher habe ich den Workaround nicht in meinen Code eingebaut.
Ich habe meine CV in Code eingesetzt wo ein Producer und 10.000 Consumer-Threads parallel arbeiten (wobei Windows dann ziemlich in die Knie geht - Windows ist halt scheiße) - die CV arbeitet einwandfrei.
Und einen Tick effizienter als die CV von Win32 ist meine CV auch, vor allem macht sie keine Spurious Wakesups (Stolen Wakeups können aber weiter passieren, das liegt in der Natur der Sache). Und sie ist sehr viel effizienter als die CV der MS C++ Standard Library (keine Ahnung wieso die Standard Library nicht die Win32 CV einsetzt, die viel effizienter ist als die Eigenimplementation der Standard Library).
-
Erst ein Langzeit-Test über mehrere Jahre wird zeigen, ob deine Implementierung richtig ist.