Hallo,
ich habe ein seltsames Problem:
Es werden 2 Threads gestartet, die die CPU für eine bestimmte Zeit vollständig beanspruchen.
Jeder Thread wird einem Kern zugewiesen (was im Grunde egal ist).
Auf einem Core2 sollte jetzt die CPU-Last 100% betragen.
Prozedur "haenge" bleibt 10 Sekunden in einer Schleife und führt Stringoperationen durch
Im "Button6Click" wird das ganze aktiviert.
* Wenn beide Zeilen (Kommentar "Thread-Bremse") auskommentiert sind, ist die CPU-Last 100% (also 2 Kerne)
(so wie erwartet; 50% pro Thread)
* Wenn eine der Problem-Zeilen(Thread-Bremse) aktiv ist, fällt die Last auf unter 30%
(das war nicht erwartet, zumindest nicht von mir
)
* Zwinge ich das Programm, nur eine CPU zu verwenden, ist die CPU-LAST 50% (nur ein Kern)
aber MIT der aktiven Zeile (Kommentar "Thred-Bremse")
* Zusammengefaßt: 2 Threads auf 2 CPUs sind langsamer als 2 Threads auf einer!
-> siehe Anzahl Durchläufe im Quelltext-Kommentar
* Ich habe festgestellt, daß die besagten Zeilen extrem hohe Kontext-Switches verursachen;
Vielleicht hängt das mit dem Speichermanagement von SetLength zusammen ?
ShortString oder HugeString führen zum gleichen Ergebnis
* Delphi 6; auf Core2 E6300
Vielleicht hat jemand eine Idee.
Vielen Dank im Voraus!
Jetzt zum Code:
Delphi-Quellcode:
procedure haenge;
var l, x:longint; s :shortstring; cnt :int64;
begin
// Str. erzeugen für pos, wenn Setlength auskommentiert
s:=''; for x:= 0 to 200 do s:= s + chr(x);
cnt:= 0; // durchlaufzähler
L:=gettickcount+10000;
while gettickcount<l do begin
// ---> ohne folgende zwei Zeilen: 111 Mio Durchläufe pro CPU-Kern, CPU-Auslastung 100%
// ---> MIT Setlength: 0.4 Mio um 25%
// * Es ist fast egal ob beide Zeilen, oder nur eine der Zeilen aktiv sind
// * Procedure "haenge" mit anderem Namen nochmal erstllen und beide getrennt
// aufrufen ändert auch nichts
// * Processexplorer zeigt extrem hohes Kontextswitching an
setlength(s, 200+ random(50) ); // Thread-Bremse 1 auf core2
s[0]:= char( 200+ random(50) ); // Thread-Bremse 2 auf core2
// irgendwelche Aktionen...
s:= copy(s, 1+ random(10), 50 + random(10) );
x:= pos('*', s);
s:= trim(s);
inc(cnt);
end;
messagebox(0, pchar('Durchläufe: '+ inttostr(cnt)), '', 0);
end;
procedure TForm1.Button6Click(Sender: TObject);
var nix,id:integer; p1,p2 :ThreadParameter; ok :boolean;
mask_alt, mask_p, mask_s :dword; hthr :THandle;
begin
id:= BeginThread(nil, 0, @haenge, nil, 0, hthr);
mask_alt:= SetThreadAffinityMask( id, 1 );
id:= BeginThread(nil, 0, @haenge, nil, 0, hthr);
mask_alt:= SetThreadAffinityMask( id, 2 );
end;