Forum > General

Parallel procedures

<< < (2/2)

MarkMLl:

--- Quote from: Arioch on October 08, 2022, 06:12:51 pm ---I believe in the end CPU afifnity is up to OS administartor to decide, not to the program.

--- End quote ---

sched_setaffinity() or pthread_setaffinity_np() on unix, noting that OP's not told us what he's using.

However in general I'd expect the OS to do a competent job of determining an appropriate allocation, this is after all the reason that the scheduler is tuned for specific submodel of CPU, cache architecture and so on.

MarkMLl

Arioch:
Maybe you can look into a lessre task of preventing threads migration.

https://stackoverflow.com/questions/13865393/any-way-to-prevent-linux-kernel-to-migrate-threads-to-other-cpus

and even https://en.wikipedia.org/wiki/Critical_section

Arioch:
https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadidealprocessor
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setprocessaffinitymask

There are similar fncitons on Windows, but

1. They can set relationships within your process, but they would not effect other processes, which can be scheduled to "rightfully yours" core and push you out.

2. I believe them to be more of suggestions to OS kernel rather than hard orders.

And, i can see a reason to pin the secondary computational thread to some one core (cache warming), but not to force main (GUI) thread to other cores.

jamie:
if you want a direct route to a simple procedure wait etc.

https://riptutorial.com/winapi/example/13881/create-a-new-thread


 Windows only of course.

if you want to LCL way which should also do the trick...

TThread base class with your code in the Procedure.

Your procedure either way will simply loop until it's complete or you can use some wait object, for example on a serial port, file or directory activity etc.

 In any case, what I do is pump a custom user message to the Main thread when it needs to be notified.
 
 That message may contain all data required or just a notice for you so check out some recent activity.

The choice is yours but as for CPU sharing, load etc. the TThread has priorities you can set to help that out.


SymbolicFrank:
To run a method in a thread and communicate through messages with other threads / the main program:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit ThreadFunction; {$mode Delphi}{$H+} {  Requires PasMP.TPasMPUnboundedQueue in the calling thread!} interface uses  Classes, SysUtils, PasMP, Variants; type   TRunFunction = class;   { TRunResult }   TRunResult = class(TObject)  protected    MyName: string;  public    Value: Variant;    Reference: TObject;    property Name: string read MyName;    constructor Create(ThisName: string);  end;   { TResultQueue }   TResultQueue = class(TPasMPUnboundedQueue<TRunResult>);   { TThreadFunction }   TThreadFunction = function(ThisThread: TRunFunction; Para1, Para2: Variant;    Para3: TObject): TRunResult of object;   { TRunFunction }   TRunFunction = class(TThread)  protected    MyName: string;    MyQueue: TResultQueue;    MyFunction: TThreadFunction;    MyPara1: Variant;    MyPara2: Variant;    MyPara3: TObject;    procedure Execute; override;  public    constructor Create(ThisName: string; ThisQueue: TResultQueue;      ThisFunction: TThreadFunction; Para1, Para2: Variant; Para3: TObject = nil);    function PostMessage(ThisValue: Variant; ThisReference: TObject = nil):      Boolean;  end;  implementation { TRunResult } constructor TRunResult.Create(ThisName: string);begin  MyName := ThisName;  Value := Null;  Reference := nil;end; { TRunFunction } procedure TRunFunction.Execute;var  r: TRunResult;begin  if Assigned(MyFunction) then  begin    r := MyFunction(Self, MyPara1, MyPara2, MyPara3);    if Assigned(MyQueue) then      MyQueue.Enqueue(r);  end;end; constructor TRunFunction.Create(ThisName: string; ThisQueue: TResultQueue;  ThisFunction: TThreadFunction; Para1, Para2: Variant; Para3: TObject);begin  inherited Create(True);   FreeOnTerminate := True;  MyName := ThisName;  MyQueue := ThisQueue;  MyFunction := ThisFunction;  MyPara1 := Para1;  MyPara2 := Para2;  MyPara3 := Para3;   Start;end; function TRunFunction.PostMessage(ThisValue: Variant; ThisReference: TObject  ): Boolean;var  r: TRunResult;begin  Result := False;   if Assigned(MyQueue) then  begin    r := TRunResult.Create(MyName);    r.Value := ThisValue;    r.Reference := ThisReference;    MyQueue.Enqueue(r);    Result := True;  end;end; end.
Warning: make everything dynamic, use separate connections/sockets for each threaded method, don't try to modify properties of the class instance from outside the thread while it is running! Your method has to be a TThreadFunction.

Navigation

[0] Message Index

[*] Previous page

Go to full version