Sign in Join
Wiki copytemporary

Parallel procedures/de

Deutsch · English · Русский · 日本語

Übersicht

Diese Seite beschreibt, wie man eine einzelne Prozedur parallel laufen lässt unter Benutzung der MTProcs Unit, die das parallel laufen lassen und die Implementierung von parallelen Algorithmen vereinfacht.

Parallele Prozeduren und Methoden werden oft in parallele Algorithmen gefunden und einige Programmiersprachen haben einen eingebauten Support für sie (z.B. OpenMP im gcc). Siehe auch hier für die Planung der Hinzufügung dieser Sprachfeatures im FPC. Einbetten dieser Sachen in die Sprache kann zur Reduzierung von Eingaben führen und erlaubt dem Compiler Code zu erzeugen, der weniger Overhead hat. Auf der anderen Seite ist hier kein einfacher Algorithmus, um Code parallel laufen zu lassen. Tatsächlich machen einfache Versuche oft den Code langsamer. Um gute Resultate zu erhalten, muss man einige Parameter spezifizieren, die der Compiler nicht voraussagen kann. Als Beispiel kann man sich die unermessliche Anzahl an Einstellungen und Diskussionen auf OpenMP ansehen. Man benötigt parallele Algorithmen. MTProcs hilft bei der Implementierung von parallelen Algorithmen.

MTProcs erhalten

Die Unit mtprocs.pas ist ein Teil des multithreadprocslaz.lpk Paket, das mittels svn von

pascal
svn co https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/components/multithreadprocs multithreadprocs

heruntergeladen werden kann.

Wie immer: Öffne das Paket multithreadprocslaz.lpk einmal in der IDE, so das es die Pfade lernt. Um das Paket in deinem Projekt zu verwenden: Benutze IDE Menu / Package / Open recent package / .../multithreadprocslaz.lpk / More / add to project um es in deinem aktuellen Projekt zu verwenden. Oder füge mittels des Projekt Inspektors hinzu.

Einfaches Beispiel

Hier ist ein einfaches Beispiel, das nichts wirklich sinnvolles macht, um zu zeigen, wie parallele Prozeduren aussehen und wie sie aufgerufen werden:

pascal
program Test;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}
  cthreads, cmem,
  {$ENDIF}
  MTProcs;

// a simple parallel procedure
procedure DoSomethingParallel(Index: PtrInt; Data: Pointer; Item: TMultiThreadProcItem);
var
  i: Integer;
begin
  WriteLn(Index);
  for i := 1 to Index * 1000000 do ; // do some work
end;

begin
  ProcThreadPool.DoParallel(@DoSomethingParallel, 1, 5, nil); // address, startindex, endindex, optional data
end.

Die Ausgabe wird ähnlich wie folgendes sein:

pascal
2
3
1
4
5

Hier einige kurze Anmerkungen. Die Details folgen später

Features

Running a procedure in parallel means:

pascal
 ProcThreadPool.MaxThreadCount:=8;

Overhead, slow down

The overhead heavily depends on the system (number and types of cores, type of shared memory, speed of critical sections, cache size). Here are some general hints:

Multi threading overhead, which is independent of the MTProcs units, but simply results from todays computer architectures:

Setting the maximum number of threads for a procedure

You can specify the maximum number of threads for a procedure as the fifth parameter.

pascal
begin
  ProcThreadPool.DoParallel(@DoSomethingParallel, 1, 10, nil, 2); // address, startindex, endindex, 
      // optional: data (here: nil), optional: maximum number of threads (here: 2)
end.

This can be useful, when the threads work on the same data, and a too many threads will create so many cache conflicts, that they slow down each other. Or when the algorithm uses a lot of WaitForIndex, so that only a few threads can actually work. Then the threads can be used for other tasks.

Wait for index / executing in order

Sometimes an Index depends on the result of a former Index. For example a common task is to first compute chunk 5 and then combine the result with the result of chunk 3. Use the WaitForIndex method for that:

pascal
procedure DoSomethingParallel(Index: PtrInt; Data: Pointer; Item: TMultiThreadProcItem);
begin
  ... compute chunk number 'Index' ...
  if Index = 5 then begin
    if not Item.WaitForIndex(3) then exit;
    ... compute ...
  end;
end;

WaitForIndex takes as an argument an Index that is lower than the current Index or a range. If it returns true, everything worked as expected. If it returns false, then an exception happened in one of the other threads.

Exceptions

If an exception occur in one of the threads, the other threads will finish normally, but will not start a new Index. The pool waits for all threads to finish and will then raise the exception. That's why you can use try..except like always:

pascal
try
  ...
  ProcThreadPool.DoParallel(...);
  ...
except
  On E: Exception do ...
end;

If there are multiple exceptions, only the first exception will be raised. To handle all exceptions, add a try..except inside your parallel method.


From the Free Pascal wiki, page "Parallel procedures/de", as it stood on 2020-02-23 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 2, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.