![]() |
SpinLock Thread Synchronization geht nicht auf QuadCore
Liste der Anhänge anzeigen (Anzahl: 2)
ich hab hier ein Quelltextbeispiel, welches einen Spinlock darstellt, welcher optimiert ist für ständiges schnelles lesen und seltenes schreiben ab und an.
Auf einer Single CPU funktioniert das wunderbar. Auf einem Quad XEON zum testen schlägt die Synchronization manchmal fehl. (Allerdings wesentlich seltener als völlig unsynchroniziert. Man sieht das am besten im angehangenen Beispiel. Auch nach längerem draufschauen auf den Code, ist mir keine Lösung eingefallen, weiß jemand Rat? vielen Dank!
Delphi-Quellcode:
//==============================================================================
procedure XMspinLock.BeginRead; begin while(FCountWR>0) do Sleep(1); InterlockedIncrement(FCountRD); end; //============================================================================== procedure XMspinLock.EndRead; begin if(InterlockedDecrement(FCountRD)<0) then raise Exception.Create('Negative read InterlockedDecrement count'); end; //============================================================================== procedure XMspinLock.BeginWrite; var wrcnt : integer; begin wrcnt:=InterlockedIncrement(FCountWR); while(FCountRD > 0) do Sleep(1); while(FCountWR > wrcnt) do Sleep(1); end; //============================================================================== procedure XMspinLock.EndWrite; begin if(InterlockedDecrement(FCountWR)<0) then raise Exception.Create('Negative write InterlockedDecrement count'); Sleep(0); end; |
Re: SpinLock Thread Synchronization geht nicht auf QuadCore
Delphi-Quellcode:
Zwei Endlosschleifen? Oder wie funktioniert das?
while(FCountRD > 0) do Sleep(1);
while(FCountWR > wrcnt) do Sleep(1) Nutze doch den TMulitReadExclusiveWriteSyncronizer (oder wie der genau hieß). |
Re: SpinLock Thread Synchronization geht nicht auf QuadCore
Zitat:
keine Endlosschleife, die Daten dürfen mehrere Thread lesen und nur einer schreiben. Wir wollten was schnelleres als dieser Dingsdabums .. TMulitReadExclusiveWriteSyncronizer .. Ohne Systemevents, und am liebsten noch nichtmal mit Interlockedfunktionen beim Lesen ... |
Re: SpinLock Thread Synchronization geht nicht auf QuadCore
Du machst es dir deutlich zu einfach. Als einfaches Beispiel schaue man sich BeginRead an: Nimm an, ein Thread hat gerade die While-Schleife beendet, aber noch nicht das InterlockedIncrement begonnen und wird nun von einem Thread unterbrochen, der BeginWrite komplett ausführt. Nachdem der erste Thread nun BeginRead beendet, besitzen beide Threads das Lock.
Im Allgemeinen wird es nicht klappen, wenn du für den Read- und den Write-Zähler zwei verschiedene Variablen verwendest, weil du sie nicht gleichzeitig aktualisieren kannst. Du kannst stattdessen zwei Hälften eines DWords verwenden, die du dann mit InterlockedCompareExchange gleichzeitig veränderst. Der Code wird allerdings deutlich komplizierter. |
Re: SpinLock Thread Synchronization geht nicht auf QuadCore
Was spricht gegen einen Kristischen Abschnitt? Warum musst du auf der Globalen Variablen arbeiten? Reicht es nicht einfach nur das Ergebnis gesichert zu schreiben?
Delphi-Quellcode:
Vermutlich bin ich damit aber auch nur am Thema vorbei, sorry falls das so sein sollte.
unit ThreadObj;
interface uses SysUtils, Classes, Windows, SyncObjs; type TDemoThread = class(TThread) private { Private-Deklarationen} Fofs: Integer; FGlobstring : string; FCriticalSection:TCriticalSection; function GetString : string; procedure SetString(value:string); protected procedure Execute; override; public constructor create; destructor destroy; override; property ValueString : string read GetString; end; implementation { TDemoThread } constructor TDemoThread.create; begin inherited Create(false); FCriticalSection:=TCriticalSection.Create; FreeOnTerminate:=true; end; destructor TDemoThread.destroy; begin FCriticalSection.free; inherited destroy; end; function TDemoThread.GetString : string; begin FCriticalSection.Acquire; try Result := FGlobString; finally FCriticalSection.Release; end; end; procedure TDemoThread.SetString(Value: string); begin FCriticalSection.Acquire; try FGlobString := Value; finally FCriticalSection.Release; end; end; procedure TDemoThread.Execute; var i: Integer; s: string; begin while not Terminated do begin s:=''; for i:=Fofs to Fofs+9 do s:=s+IntToStr(i mod 10); Inc(Fofs); if Fofs > 9 then Fofs:=0; SetString(s); end; end; end. Gruss Thorsten |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:32 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz