Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   TParallel for: wie Schleife abbrechen? (https://www.delphipraxis.net/182858-tparallel-wie-schleife-abbrechen.html)

Harry Stahl 21. Nov 2014 21:56

TParallel for: wie Schleife abbrechen?
 
Leider sind die Informationen zur TParallel-Library noch sehr spärlich.

Wie kann man eine TParallel.for schleife eigentlich vorzeitig abbrechen?
Also abbrechen, bevor alle Iterationen durchlaufen sind?

Ein "break" scheint es nicht zu geben.

Sir Rufo 21. Nov 2014 22:09

AW: TParallel for: wie Schleife abbrechen?
 
Du musst dir ein zentrales Break selber bauen ...
Delphi-Quellcode:
procedure Foo;
var
  LBreak: Boolean;
  LValue: Integer;
begin
  LBreak := False;
  LValue := 0;
  TParallel.&For( 1, 1000,
      procedure( L: Integer )
    begin
      if not LBreak
      then
        begin
          Inc( LValue );
          LBreak := L = 100;
        end;
    end );
  Writeln( LValue );
end;

Harry Stahl 21. Nov 2014 22:27

AW: TParallel for: wie Schleife abbrechen?
 
OK, das geht, aber offensichtlich wird die For Schleife dann trotzdem die vorgesehene Anzahl durchlaufen, nur, dass eben nichts abgearbeitet wird.

Gibt es da wirklich nichts anderes?

Mal Frage am Rande: Warum verwendest Du immer "Tparallel.&For", statt "TParallel.For"?

In der Hilfe steht es auch mit "&", warum eigentlich?

Sir Rufo 21. Nov 2014 22:30

AW: TParallel for: wie Schleife abbrechen?
 
Ja, da gibt es doch ein Break (mir war doch auch so :oops:)
Delphi-Quellcode:
procedure Foo;
var
  LValue: Integer;
begin
  LValue := 0;
  TParallel.&For( 1, 1000,
      procedure( L: Integer; S: TParallel.TLoopState )
    begin
      if not S.ShouldExit
      then
        begin
          Inc( LValue );
          if L = 500
          then
            S.Break;
        end;
    end );
  Writeln( LValue );
end;
Da wird auf jeden Fall früher abgebrochen, allerdings laufen ein paar Tasks noch durch die Schleife. Sieht man schön, wenn man das ausführt
Delphi-Quellcode:
procedure Foo;
var
  LValue: Integer;
begin
  LValue := 0;
  TParallel.&For( 1, 1000,
      procedure( L: Integer; S: TParallel.TLoopState )
    begin
//      if not S.ShouldExit
//      then
//        begin
          Inc( LValue );
          if L = 500
          then
            S.Break;
//        end;
    end );
  Writeln( LValue );
end;
Bei mir kommt dann regelmäßig 529 heraus.

Sir Rufo 21. Nov 2014 22:33

AW: TParallel for: wie Schleife abbrechen?
 
Zitat:

Zitat von Harry Stahl (Beitrag 1280710)
Mal Frage am Rande: Warum verwendest Du immer "Tparallel.&For", statt "TParallel.For"?

In der Hilfe steht es auch mit "&", warum eigentlich?

Weil
Delphi-Quellcode:
for
ein reserviertes Wort ist. Und um das so zu deklarieren muss man ein
Delphi-Quellcode:
&
davor setzen.
Delphi-Quellcode:
TFoo = class
  procedure &For;
  procedure &Type;
  procedure &Begin;
  procedure &End;
  procedure &Class;
  procedure &procedure;
end;
;)

Harry Stahl 21. Nov 2014 22:41

AW: TParallel for: wie Schleife abbrechen?
 
Super, so was hatte ich gesucht, aber leider nicht gefunden.

Sir Rufo 21. Nov 2014 22:50

AW: TParallel for: wie Schleife abbrechen?
 
Zitat:

Zitat von Harry Stahl (Beitrag 1280713)
Super, so was hatte ich gesucht, aber leider nicht gefunden.

Steht aber in der Doku http://docwiki.embarcadero.com/Libra....TParallel.For
Delphi-Quellcode:
class function &For(Sender: TObject; ALowInclusive, AHighInclusive: Integer; AIteratorEvent: TIteratorEvent): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; ALowInclusive, AHighInclusive: Integer; AIteratorEvent: TIteratorEvent; APool: TThreadPool): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; ALowInclusive, AHighInclusive: Integer; AIteratorEvent: TIteratorStateEvent): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; ALowInclusive, AHighInclusive: Integer; AIteratorEvent: TIteratorStateEvent; APool: TThreadPool): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; AStride, ALowInclusive, AHighInclusive: Integer; AIteratorEvent: TIteratorEvent): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; AStride, ALowInclusive, AHighInclusive: Integer; AIteratorEvent: TIteratorEvent; APool: TThreadPool): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; AStride, ALowInclusive, AHighInclusive: Integer; AIteratorEvent: TIteratorStateEvent): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; AStride, ALowInclusive, AHighInclusive: Integer; AIteratorEvent: TIteratorStateEvent; APool: TThreadPool): TLoopResult; overload; static; inline;
class function &For(ALowInclusive, AHighInclusive: Integer; const AIteratorEvent: TProc<Integer>): TLoopResult; overload; static; inline;
class function &For(ALowInclusive, AHighInclusive: Integer; const AIteratorEvent: TProc<Integer>; APool: TThreadPool): TLoopResult; overload; static; inline;
{ da } class function &For(ALowInclusive, AHighInclusive: Integer; const AIteratorEvent: TProc<Integer, TLoopState>): TLoopResult; overload; static; inline;
{ da } class function &For(ALowInclusive, AHighInclusive: Integer; const AIteratorEvent: TProc<Integer, TLoopState>; APool: TThreadPool): TLoopResult; overload; static; inline;
class function &For(AStride, ALowInclusive, AHighInclusive: Integer; const AIteratorEvent: TProc<Integer>): TLoopResult; overload; static; inline;
class function &For(AStride, ALowInclusive, AHighInclusive: Integer; const AIteratorEvent: TProc<Integer>; APool: TThreadPool): TLoopResult; overload; static; inline;
{ da } class function &For(AStride, ALowInclusive, AHighInclusive: Integer; const AIteratorEvent: TProc<Integer, TLoopState>): TLoopResult; overload; static; inline;
{ da } class function &For(AStride, ALowInclusive, AHighInclusive: Integer; const AIteratorEvent: TProc<Integer, TLoopState>; APool: TThreadPool): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; ALowInclusive, AHighInclusive: Int64; AIteratorEvent: TIteratorEvent64): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; ALowInclusive, AHighInclusive: Int64; AIteratorEvent: TIteratorEvent64; APool: TThreadPool): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; ALowInclusive, AHighInclusive: Int64; AIteratorEvent: TIteratorStateEvent64): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; ALowInclusive, AHighInclusive: Int64; AIteratorEvent: TIteratorStateEvent64; APool: TThreadPool): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; AStride, ALowInclusive, AHighInclusive: Int64; AIteratorEvent: TIteratorEvent64): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; AStride, ALowInclusive, AHighInclusive: Int64; AIteratorEvent: TIteratorEvent64; APool: TThreadPool): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; AStride, ALowInclusive, AHighInclusive: Int64; AIteratorEvent: TIteratorStateEvent64): TLoopResult; overload; static; inline;
class function &For(Sender: TObject; AStride, ALowInclusive, AHighInclusive: Int64; AIteratorEvent: TIteratorStateEvent64; APool: TThreadPool): TLoopResult; overload; static; inline;
class function &For(ALowInclusive, AHighInclusive: Int64; const AIteratorEvent: TProc<Int64>): TLoopResult; overload; static; inline;
class function &For(ALowInclusive, AHighInclusive: Int64; const AIteratorEvent: TProc<Int64>; APool: TThreadPool): TLoopResult; overload; static; inline;
{ da } class function &For(ALowInclusive, AHighInclusive: Int64; const AIteratorEvent: TProc<Int64, TLoopState>): TLoopResult; overload; static; inline;
{ da } class function &For(ALowInclusive, AHighInclusive: Int64; const AIteratorEvent: TProc<Int64, TLoopState>; APool: TThreadPool): TLoopResult; overload; static; inline;
class function &For(AStride, ALowInclusive, AHighInclusive: Int64; const AIteratorEvent: TProc<Int64>): TLoopResult; overload; static; inline;
class function &For(AStride, ALowInclusive, AHighInclusive: Int64; const AIteratorEvent: TProc<Int64>; APool: TThreadPool): TLoopResult; overload; static; inline;
{ da } class function &For(AStride, ALowInclusive, AHighInclusive: Int64; const AIteratorEvent: TProc<Int64, TLoopState>): TLoopResult; overload; static; inline;
{ da } class function &For(AStride, ALowInclusive, AHighInclusive: Int64; const AIteratorEvent: TProc<Int64, TLoopState>; APool: TThreadPool): TLoopResult; overload; static; inline;
Und wenn ich nicht weiß, was
Delphi-Quellcode:
TLoopState
oder
Delphi-Quellcode:
TLoopResult
ist, und die Doku nicht weiterweiß, dann einfach ein STRG-Klick auf das Unbekannte und direkt im Quelltest nachschauen ;)

BTW:
Delphi-Quellcode:
TIteratorStateEvent
/
Delphi-Quellcode:
TIteratorStateEvent64
haben auch noch den
Delphi-Quellcode:
TLoopState
:)

Harry Stahl 21. Nov 2014 23:00

AW: TParallel for: wie Schleife abbrechen?
 
Ich muss gestehen, das hatte ich gesehen, aber das Gewünschte nicht gefunden (ist ja auch ein wenig unübersichtlich...).

Was soll eigentlich s.shouldexit bewirken? Wenn man das aufruft, hat das anscheinend keine Auswirkungen?

In System.Threading gibt es das da:

Delphi-Quellcode:
class function TParallel.ForWorker...

 while (I < ToExclusive) and ((SharedFlags.LoopStateFlags = []) or not SharedFlags.ShouldExit) do
EDIT: Oh, jetzt gesehen, dass Shoudexit einen Wert zurückgibt, nicht setzt. Wäre aber gut, wenn man die Rückgabe von SharedFlags.ShouldExit mit True hinkriegen könnte, dann wir die While-Schleife unterbrochen

Sir Rufo 21. Nov 2014 23:10

AW: TParallel for: wie Schleife abbrechen?
 
Öhm, das ist doch offensichtlich und darum habe ich den Code doch auch in 2 Variationen eingestellt. Einmal mit Abfrage
Delphi-Quellcode:
s.ShouldExit
und einmal ohne. Bei beiden wird die Verarbeitung der Tasks vorzeitig abgebrochen, allerdings sind einige Tasks schon über dem PointOfNoReturn und werden trotzdem noch durch die Worker-Threads verarbeitet.

Und genau für diese durchgerutschten Tasks frage ich den LoopState
Delphi-Quellcode:
TLoopState
ab. Und wenn man vorher ein
Delphi-Quellcode:
TLoopState.Break
aufgerufen hat, dann liefert
Delphi-Quellcode:
TLoopState.ShouldExit
ganz lapidar ein
Delphi-Quellcode:
True
.

Genau das wollen wir doch haben ... oder nicht?

himitsu 21. Nov 2014 23:14

AW: TParallel for: wie Schleife abbrechen?
 
Man hätte es aber auch einfacher implementieren können, indem man z.B. auch auf Delphi-Referenz durchsuchenAbort reagiert und dann die anderen Schleifen-Threads abbricht (Break-State setzt). :stupid:

Aber wenn man in dem For-Event etwas längeres macht, oder eine Schleife, dann sollte man da natürlich auch den State prüfen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:15 Uhr.
Seite 1 von 2  1 2      

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