AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Problem mit 2 Threads und CPU-Auslastung
Thema durchsuchen
Ansicht
Themen-Optionen

Problem mit 2 Threads und CPU-Auslastung

Ein Thema von treepwood · begonnen am 26. Mai 2008 · letzter Beitrag vom 28. Mai 2008
Antwort Antwort
treepwood

Registriert seit: 26. Mai 2008
5 Beiträge
 
#1

Problem mit 2 Threads und CPU-Auslastung

  Alt 26. Mai 2008, 21:42
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;
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#2

Re: Problem mit 2 Threads und CPU-Auslastung

  Alt 27. Mai 2008, 08:42
Du hast schon richtig geahnt, die Threads blockieren sich gegenseitig.
Der Speichermanager stellt sicher, dass nur ein Thread gleichzeitig auf ihn zugreift. Wobei ich jetzt nicht weis, was setlength mit einem shortstring macht.

btw.: Du solltest die ThreadProc (Haenge) mal mit einem 32-bit-Parameter und als stdcall deklarieren.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
treepwood

Registriert seit: 26. Mai 2008
5 Beiträge
 
#3

Re: Problem mit 2 Threads und CPU-Auslastung

  Alt 27. Mai 2008, 15:14
Zitat von sirius:
Du hast schon richtig geahnt, die Threads blockieren sich gegenseitig.
Der Speichermanager stellt sicher, dass nur ein Thread gleichzeitig auf ihn zugreift. Wobei ich jetzt nicht weis, was setlength mit einem shortstring macht.

btw.: Du solltest die ThreadProc (Haenge) mal mit einem 32-bit-Parameter und als stdcall deklarieren.

Die Frage ist nur, warum blockieren sich die Threads gegenseitig ?
Jeder Thread sollte seinen eigenen Heap mit eigenem String haben.
Kann es sein, daß der Speicher von den Thread geteilt wird ?

Mit Long/Huge-String passiert das Gleiche wie bei shortstring oder Ansistring.
Jeglicher Zugriff auf den Speicher mit z.B. Pchar; getmem(P, 100);...
verursacht das selbe Problem, auch ohne SetLength

ich habe den Prozedurkopf wie folgt geändert:
procedure haenge (param_nicht_verwendet :longint); stdcall; leider bleibt das Ergebnis gleich.
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#4

Re: Problem mit 2 Threads und CPU-Auslastung

  Alt 27. Mai 2008, 15:21
Versuch mal den Memory-Manager FastMM.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#5

Re: Problem mit 2 Threads und CPU-Auslastung

  Alt 27. Mai 2008, 15:23
Der Prozedurkopf hat natürlich keinen Einfluss auf die Speicherverwaltung. War nur ein Tipp nebenbei. Und Windows freut sich
Die Speicherverwaltung von Delphi hat eine Critical Section und es darf eben nur ein Thread gleichzeitig darauf zugreifen. Ein Thread hat ja nur einen eigenen Stack. Heap, Datensegment und Codesegement sind ja identisch.

Aus der Getmem.inc:
Delphi-Quellcode:
function SysReallocMem(p: Pointer; size: Integer): Pointer;
// Resize memory block.
var
  n: Pointer; oldSize: Integer;
begin

  ...
  try
    if IsMultiThread then EnterCriticalSection(heapLock);
  
    ...

  finally
    if IsMultiThread then LeaveCriticalSection(heapLock);
  end;

end;
Und IsMultiThread wird durch BeginThread auf True gesetzt. Genau deswegen soll man ja auch BeginThread verwenden und nicht den direkten API-Aufruf von CreateThread.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.105 Beiträge
 
Delphi 11 Alexandria
 
#6

Re: Problem mit 2 Threads und CPU-Auslastung

  Alt 27. Mai 2008, 15:38
Moin treepwood,

erst einmal herzlich willkommen hier in der Delphi-PRAXiS.

Ich habe da noch eine Anmerkung zu der CPU-Last, die angezeigt wird.
Diese Werte sind nicht absolut zu sehen, sondern relativ, denn es ist nicht gesagt, dass die Kerne auch gerade mit voller Taktung laufen, denn die wird auch dynamisch an die Erfordernisse angepasst.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
treepwood

Registriert seit: 26. Mai 2008
5 Beiträge
 
#7

Re: Problem mit 2 Threads und CPU-Auslastung

  Alt 28. Mai 2008, 12:15
Zitat von shmia:
Versuch mal den Memory-Manager FastMM.
Das habe ich bereits probiert.
Das Ergebnis sieht wie folgt aus:

Code:
MemoryManager | eine CPU | 2 CPUs |Kontextswitching/Interwall (auf 2 CPUs)
--------------|----------|--------|---------------------------------------
Standard-MM: | ~4.3*    | ~0.4*  | ~70000**
FastMM4:     | ~6*      | ~5.4*  | ~700**
BrainMM:     | ~2.6*    | ~3.2*  | ~700** 
[*in Millionen Durchläufen auf P4 HT] [** geschätzt mit processexplorer]
Das Programm kann nur von einem Thread pro Kern profitieren,
wenn der Rest des Programms keine Speicheroperationen durchführt.
Wenn noch mehr Speicheroperationen dazu kommen, kann die Methode mit 2 Thread anscheinend nicht schneller werden.
Alternativ müßte man einen Tread in einem eigenen Codesegment starten
(also wohl ein eigenes Programm).

Leider kann ich momentan nicht auf einem echten Core2 Testen.
Das Ergebnis sollte aber trotzdem interessant sein...

Gibt es keine Möglichkeit, einen speicherunabhängigen Thread zu starten ?
  Mit Zitat antworten Zitat
treepwood

Registriert seit: 26. Mai 2008
5 Beiträge
 
#8

Re: Problem mit 2 Threads und CPU-Auslastung

  Alt 28. Mai 2008, 12:21
Zitat von sirius:
Der Prozedurkopf hat natürlich keinen Einfluss auf die Speicherverwaltung. War nur ein Tipp nebenbei. Und Windows freut sich
Die Speicherverwaltung von Delphi hat eine Critical Section und es darf eben nur ein Thread gleichzeitig darauf zugreifen. Ein Thread hat ja nur einen eigenen Stack. Heap, Datensegment und Codesegement sind ja identisch.
Achso, danke für den Hinweis
Ich müßte also einen Thread außerhalb meiner Anwendung starten, damit
die Kontextswitches verhindert werden könnten. Mit den anderen MemoryManagern erreicht man zwar eine Besserung, aber leider switcht das Programm immer noch recht viel.
  Mit Zitat antworten Zitat
treepwood

Registriert seit: 26. Mai 2008
5 Beiträge
 
#9

Re: Problem mit 2 Threads und CPU-Auslastung

  Alt 28. Mai 2008, 12:28
Zitat von Christian Seehase:
Ich habe da noch eine Anmerkung zu der CPU-Last, die angezeigt wird.
Diese Werte sind nicht absolut zu sehen, sondern relativ, denn es ist nicht gesagt, dass die Kerne auch gerade mit voller Taktung laufen, denn die wird auch dynamisch an die Erfordernisse angepasst.
Danke, ich kenne die Seite schon recht lange. Es war an der Zeit sich anzumelden

Mein Core2 schaltet den Multiplikator ab ca. 25% automatisch auf Maximum.
Das Beispileprogramm ist auch so gestalltet, daß es voll auf der CPU "steht".
Der Lüfter springt auch recht schnell an. Ich denke, das sollte schon stimmen.

Du hast Recht, daß die CPU-Last beim Kontextswitching sofort runtergeht.
Die Lösung des Problems sollte genau dies verhinden. (1 Thread = quasi kein Kontextswitching)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz