diff --git a/components/multithreadprocs/examples/parallelloop1.lpi b/components/multithreadprocs/examples/parallelloop1.lpi new file mode 100644 index 000000000..874c8e7f2 --- /dev/null +++ b/components/multithreadprocs/examples/parallelloop1.lpi @@ -0,0 +1,50 @@ + + + + + + + + + + + + + </General> + <VersionInfo> + <ProjectVersion Value=""/> + </VersionInfo> + <PublishOptions> + <Version Value="2"/> + <IgnoreBinaries Value="False"/> + <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> + <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/> + </PublishOptions> + <RunParams> + <local> + <FormatVersion Value="1"/> + <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/> + </local> + </RunParams> + <RequiredPackages Count="1"> + <Item1> + <PackageName Value="MultiThreadProcsLaz"/> + <MinVersion Valid="True"/> + <DefaultFilename Value="../multithreadprocslaz.lpk"/> + </Item1> + </RequiredPackages> + <Units Count="1"> + <Unit0> + <Filename Value="parallelloop1.lpr"/> + <IsPartOfProject Value="True"/> + <UnitName Value="ParallelLoop1"/> + </Unit0> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="8"/> + <Other> + <CompilerPath Value="$(CompPath)"/> + </Other> + </CompilerOptions> +</CONFIG> diff --git a/components/multithreadprocs/examples/parallelloop1.lpr b/components/multithreadprocs/examples/parallelloop1.lpr new file mode 100644 index 000000000..274430266 --- /dev/null +++ b/components/multithreadprocs/examples/parallelloop1.lpr @@ -0,0 +1,107 @@ +{ Example for a parallel loop with MTProcs. + + Copyright (C) 2009 Mattias Gaertner mattias@freepascal.org + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version with the following modification: + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent modules,and + to copy and distribute the resulting executable under terms of your choice, + provided that you also meet, for each linked independent module, the terms + and conditions of the license of that module. An independent module is a + module which is not derived from or based on this library. If you modify + this library, you may extend this exception to your version of the library, + but you are not obligated to do so. If you do not wish to do so, delete this + exception statement from your version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +} +program ParallelLoop1; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX} + cthreads, cmem, + {$ENDIF} + Classes, SysUtils, MTProcs; + +type + TFindBestData = record + List: TList; + Value: Pointer; + BlockCount: integer; + Results: array of integer; + end; + PFindBestData = ^TFindBestData; + +procedure FindBestParallel(Index: PtrInt; Data: Pointer; Item: TMultiThreadProcItem); +var + i: integer; +begin + with PFindBestData(Data)^ do begin + Results[Index]:=-1; + i:=Index; + while i<List.Count-1 do begin + if List[i]=Value then // hier wuerde die teure Vergleichsoperation stehen + Results[Index]:=i; + inc(i,BlockCount); + end; + end; +end; + +function FindBest(aList: TList; aValue: Pointer): integer; +var + Index: integer; + Data: TFindBestData; +begin + with Data do begin + List:=aList; + Value:=aValue; + BlockCount:=ProcThreadPool.MaxThreadCount; + SetLength(Results,BlockCount); + ProcThreadPool.DoParallel(@FindBestParallel,0,BlockCount-1,@Data); + // Ergebnisse zusammenfassen + Result:=-1; + for Index:=0 to BlockCount-1 do + if Results[Index]>=0 then + Result:=Results[Index]; + end; +end; + +function FindBest1(List: TList; Value: Pointer): integer; +var + i: integer; +begin + Result:=-1; + i:=0; + while i<List.Count do begin + if List[i]=Value then // hier wuerde die teure Vergleichsoperation stehen + Result:=i; + inc(i); + end; +end; + +var + List: TList; + i: Integer; +begin + List:=TList.Create; + for i:=0 to 100000000 do + List.Add(Pointer(i)); + i:=FindBest(List,Pointer(9999)); + //i:=FindBest1(List,Pointer(9999)); + writeln('i=',i); +end. + diff --git a/components/multithreadprocs/examples/recursivemtp1.lpi b/components/multithreadprocs/examples/recursivemtp1.lpi new file mode 100644 index 000000000..fdef67366 --- /dev/null +++ b/components/multithreadprocs/examples/recursivemtp1.lpi @@ -0,0 +1,50 @@ +<?xml version="1.0"?> +<CONFIG> + <ProjectOptions> + <Version Value="7"/> + <General> + <Flags> + <LRSInOutputDirectory Value="False"/> + </Flags> + <SessionStorage Value="InProjectDir"/> + <MainUnit Value="0"/> + <TargetFileExt Value=""/> + <Title Value="recursivemtp1"/> + </General> + <VersionInfo> + <ProjectVersion Value=""/> + </VersionInfo> + <PublishOptions> + <Version Value="2"/> + <IgnoreBinaries Value="False"/> + <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> + <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/> + </PublishOptions> + <RunParams> + <local> + <FormatVersion Value="1"/> + <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/> + </local> + </RunParams> + <RequiredPackages Count="1"> + <Item1> + <PackageName Value="MultiThreadProcsLaz"/> + <MinVersion Valid="True"/> + <DefaultFilename Value="../multithreadprocslaz.lpk"/> + </Item1> + </RequiredPackages> + <Units Count="1"> + <Unit0> + <Filename Value="recursivemtp1.lpr"/> + <IsPartOfProject Value="True"/> + <UnitName Value="RecursiveMTP1"/> + </Unit0> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="8"/> + <Other> + <CompilerPath Value="$(CompPath)"/> + </Other> + </CompilerOptions> +</CONFIG> diff --git a/components/multithreadprocs/examples/recursivemtp1.lpr b/components/multithreadprocs/examples/recursivemtp1.lpr new file mode 100644 index 000000000..bf95dc5f2 --- /dev/null +++ b/components/multithreadprocs/examples/recursivemtp1.lpr @@ -0,0 +1,49 @@ +program RecursiveMTP1; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX} + cthreads, cmem, + {$ENDIF} + MTProcs; + +type + TArrayOfInteger = array of integer; +var + Items: TArrayOfInteger; + +type + TFindMaximumParallelData = record + Items: TArrayOfInteger; + Left, Middle, Right: integer; + LeftMaxIndex, RightMaxIndex: integer; + end; + PFindMaximumParallelData = ^TFindMaximumParallelData; + +procedure FindMaximumParallel(Index: PtrInt; Data: Pointer; Item: TMultiThreadProcItem); +var + Params: PFindMaximumParallelData absolute Data; + LeftParams, RightParams: TFindMaximumParallelData; +begin + if Params^.Left+1000>Params^.Right then begin + // compute the maximum of the few remaining items + Params^.LeftMaxIndex:=Params^.Items[Params^.Left]; + for i:=Params^.Left+1 to Params^.Right do + if Params^.Items[i]>Params^.LeftMaxIndex then + end else begin + + end; +end; + +function FindMaximumIndex(Items: TArrayOfInteger): integer; +begin + +end; + +begin + SetLength(Items,10000000); + for i:=0 to length(Items)-1 do Items[i]:=Random(1000); + ProcThreadPool.DoParallel(@DoSomethingParallel,1,5,nil); // address, startindex, endindex, optional data +end. + diff --git a/components/multithreadprocs/examples/simplemtp1.lpi b/components/multithreadprocs/examples/simplemtp1.lpi new file mode 100644 index 000000000..2dfd905dc --- /dev/null +++ b/components/multithreadprocs/examples/simplemtp1.lpi @@ -0,0 +1,51 @@ +<?xml version="1.0"?> +<CONFIG> + <ProjectOptions> + <PathDelim Value="/"/> + <Version Value="7"/> + <General> + <Flags> + <LRSInOutputDirectory Value="False"/> + </Flags> + <SessionStorage Value="InProjectDir"/> + <MainUnit Value="0"/> + <TargetFileExt Value=""/> + <Title Value="simplemtp1"/> + </General> + <VersionInfo> + <ProjectVersion Value=""/> + </VersionInfo> + <PublishOptions> + <Version Value="2"/> + <IgnoreBinaries Value="False"/> + <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> + <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/> + </PublishOptions> + <RunParams> + <local> + <FormatVersion Value="1"/> + <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/> + </local> + </RunParams> + <RequiredPackages Count="1"> + <Item1> + <PackageName Value="MultiThreadProcsLaz"/> + <MinVersion Valid="True"/> + <DefaultFilename Value="../multithreadprocslaz.lpk"/> + </Item1> + </RequiredPackages> + <Units Count="1"> + <Unit0> + <Filename Value="simplemtp1.lpr"/> + <IsPartOfProject Value="True"/> + <UnitName Value="SimpleMTP1"/> + </Unit0> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="8"/> + <Other> + <CompilerPath Value="$(CompPath)"/> + </Other> + </CompilerOptions> +</CONFIG> diff --git a/components/multithreadprocs/examples/simplemtp1.lpr b/components/multithreadprocs/examples/simplemtp1.lpr new file mode 100644 index 000000000..f1b217adf --- /dev/null +++ b/components/multithreadprocs/examples/simplemtp1.lpr @@ -0,0 +1,23 @@ +program SimpleMTP1; + +{$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. + diff --git a/components/multithreadprocs/mtprocs.pas b/components/multithreadprocs/mtprocs.pas index 97bed85b0..225014b6b 100644 --- a/components/multithreadprocs/mtprocs.pas +++ b/components/multithreadprocs/mtprocs.pas @@ -32,6 +32,7 @@ uses type TProcThreadGroup = class; TProcThreadPool = class; + TProcThread = class; { TMultiThreadProcItem } @@ -48,6 +49,7 @@ type private FGroup: TProcThreadGroup; FIndex: PtrInt; + FThread: TProcThread; FWaitingForIndexEnd: PtrInt; FWaitingForIndexStart: PtrInt; fWaitForPool: PRTLEvent; @@ -60,6 +62,7 @@ type property Group: TProcThreadGroup read FGroup; property WaitingForIndexStart: PtrInt read FWaitingForIndexStart; property WaitingForIndexEnd: PtrInt read FWaitingForIndexEnd; + property Thread: TProcThread read FThread; end; { TProcThread } @@ -292,6 +295,7 @@ begin inherited Create(true); fItem:=TMultiThreadProcItem.Create; fItem.fWaitForPool:=RTLEventCreate; + fItem.FThread:=Self; end; destructor TProcThread.Destroy; diff --git a/components/multithreadprocs/mtputils.pas b/components/multithreadprocs/mtputils.pas index 4c5a6a857..fbaba95c9 100644 --- a/components/multithreadprocs/mtputils.pas +++ b/components/multithreadprocs/mtputils.pas @@ -141,8 +141,8 @@ begin // For example: BlockCnt = 5 => Index in 0..4 // fBlockCntPowOf2Offset = 3 (=8-5) // NormIndex = Index + 3 => NormIndex in 3..7 - i:=0; NormIndex:=Index+fBlockCntPowOf2Offset; + i:=0; repeat Range:=1 shl i; if NormIndex and Range=0 then break; @@ -150,18 +150,18 @@ begin MergeIndex:=NormIndex-Range-fBlockCntPowOf2Offset; if (MergeIndex+Range-1>=0) then begin // wait until left blocks have finished - WriteLn('TParallelSortPointerList.LWTSort Index=',Index,' wait for block ',MergeIndex); + //WriteLn('TParallelSortPointerList.LWTSort Index=',Index,' wait for block ',MergeIndex); if (MergeIndex>=0) and (not Item.WaitForIndex(MergeIndex)) then exit; // compute left and right block bounds M:=L; L:=(MergeIndex-Range+1)*fBlockSize; if L<0 then L:=0; - WriteLn('TParallelSortPointerList.LWTSort Index=',Index,' merge blocks ',L,' ',M,' ',R); + //WriteLn('TParallelSortPointerList.LWTSort Index=',Index,' merge blocks ',L,' ',M,' ',R); MergeSort(L,M,R,false); end; inc(i); until false; - WriteLn('TParallelSortPointerList.LWTSort END Index='+IntToStr(Index)); + //WriteLn('TParallelSortPointerList.LWTSort END Index='+IntToStr(Index)); end; constructor TParallelSortPointerList.Create(aList: PPointer; aCount: PtrInt;