Recent

Author Topic: Parallel procedures  (Read 992 times)

beria

  • Jr. Member
  • **
  • Posts: 70
Parallel procedures
« on: October 08, 2022, 03:41:12 pm »
Question! An important one! Urgent! I hope who knows...
 Is it possible to write a procedure in FPC which is guaranteed to work outside of using the main program thread, even if it is pending and idle with zero load.....  That is, in any case, involving only and exclusively other physical and logical processors. If anything, I use the standard calls of the "MTProcs" module, but it's no problem to rewrite everything for any alternate library as well...
The methods built into the LCL interface biblioteks are not suggested, because I don't use them at all...
ps: I suspect that the question is very simple, but I really didn't understand it, even after reading all the written sources.... :-(
pps: it's the third day I can't figure it out...



Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: Parallel procedures
« Reply #1 on: October 08, 2022, 03:51:54 pm »
procedure in FPC which is guaranteed to work outside of using the main program thread, even if it is pending and idle with zero load

That is, in any case, involving only and exclusively other physical and logical processors. If anything, I use the standard calls of the "MTProcs" module, but it's no problem to rewrite everything for any alternate library as well...

Those all are different things.

1. running in other thread (on any core)
2. running on different virtual core (any physical core) - not every CPU have (and have enabled) HyperThreading or SMT; AMD Bullldozer cores are half-phyisical half-virtual, flamewars about properly counting and comparing them to Intel HT cores were fierce
3. running on different physical core (on any processor)
4. outside on different processor  - not many mainboards today have more than one processor

What exactly do you want and why?

What should your procedure do if called from main thread?

What does "other core/processor" even mean when main thread "is pending and idle with zero load"?
What you said in other words means the main thread does not exist this moment on none of the cores at all, every core this moment is "different" core.

beria

  • Jr. Member
  • **
  • Posts: 70
Re: Parallel procedures
« Reply #2 on: October 08, 2022, 05:48:07 pm »
procedure in FPC which is guaranteed to work outside of using the main program thread, even if it is pending and idle with zero load

That is, in any case, involving only and exclusively other physical and logical processors. If anything, I use the standard calls of the "MTProcs" module, but it's no problem to rewrite everything for any alternate library as well...

Those all are different things.

1. running in other thread (on any core)
2. running on different virtual core (any physical core) - not every CPU have (and have enabled) HyperThreading or SMT; AMD Bullldozer cores are half-phyisical half-virtual, flamewars about properly counting and comparing them to Intel HT cores were fierce
3. running on different physical core (on any processor)
4. outside on different processor  - not many mainboards today have more than one processor

What exactly do you want and why?

What should your procedure do if called from main thread?

What does "other core/processor" even mean when main thread "is pending and idle with zero load"?
What you said in other words means the main thread does not exist this moment on none of the cores at all, every core this moment is "different" core.
No argument. That's a poor way of putting it. I'll try a better one...
How to make the procedure use only those physical (logical) processors that are outside the main program thread....
That is, at the moment of start of a parallelized computing procedure, the load on that thread which provides the main program's logic should not change in any way...
At the moment, the default logic for the console application, as can be seen by the CPU load, evenly and equally, loads all the existing physical and logical processors....
Or alternatively, I need to define the whole program as one of the threads, and then let the thread manager manage them by its own logic, but this is not at all what I want....

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: Parallel procedures
« Reply #3 on: October 08, 2022, 06:06:29 pm »
How to make the procedure use only those physical (logical) processors that are outside the main program thread....

You've not told us what OS you're running. On unix you'd use whatever facilities are available to set process affinity... which might or might not separate things at the thread level (you need to consider the implication of multiple threads sharing memory, which can play havoc on a system with multi-level cache).

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: Parallel procedures
« Reply #4 on: October 08, 2022, 06:12:51 pm »
> That is, at the moment of start of a parallelized computing procedure, the load on that thread which provides the main program's logic should not change in any way...

In relaxed term - you need to set your computing thread to be low-priority, so the main thread would keep having upper hand over it, if they clash.

And i think that is not possible in general terms - there are dozens if not hundreds of other processes in the system and you are not in control of their load.
They can increase their own load any second, which would possbily be added burden to your CPU cache and execution units.

I believe in the end CPU afifnity is up to OS administartor to decide, not to the program.

It seems you want your main thread to exclusively own some CPU core and not let anyone else share it.
If i would notice any program on my 3-cores desktop trying to pull it behind my back - i would be very upset.

So it seems you have to provide documentation to OS administrators how to setup their OS to make best use of your program, IF they would opt-in. They, not you.

https://en.wikipedia.org/wiki/Processor_affinity
https://stackoverflow.com/questions/1407786/how-to-set-cpu-affinity-of-a-particular-pthread
https://stackoverflow.com/questions/762961/setthreadaffinitymask-is-ignored-any-ideas
https://winbuzzer.com/2020/07/03/how-to-set-cpu-affinity-in-windows-10-with-task-manager-or-system-properties-xcxwbt/
https://windowsnotes.ru/powershell-2/nastrojka-processor-affinity-s-pomoshhyu-powershell/

et cetera

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: Parallel procedures
« Reply #5 on: October 08, 2022, 06:25:07 pm »
I believe in the end CPU afifnity is up to OS administartor to decide, not to the program.

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
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: Parallel procedures
« Reply #6 on: October 08, 2022, 06:25:36 pm »

Arioch

  • Sr. Member
  • ****
  • Posts: 421
Re: Parallel procedures
« Reply #7 on: October 08, 2022, 06:36:32 pm »
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

  • Hero Member
  • *****
  • Posts: 6131
Re: Parallel procedures
« Reply #8 on: October 08, 2022, 08:58:20 pm »
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.


The only true wisdom is knowing you know nothing

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: Parallel procedures
« Reply #9 on: October 14, 2022, 10:26:45 am »
To run a method in a thread and communicate through messages with other threads / the main program:

Code: Pascal  [Select][+][-]
  1. unit ThreadFunction;
  2.  
  3. {$mode Delphi}{$H+}
  4.  
  5. {
  6.   Requires PasMP.TPasMPUnboundedQueue in the calling thread!
  7. }
  8.  
  9. interface
  10.  
  11. uses
  12.   Classes, SysUtils, PasMP, Variants;
  13.  
  14. type
  15.  
  16.   TRunFunction = class;
  17.  
  18.   { TRunResult }
  19.  
  20.   TRunResult = class(TObject)
  21.   protected
  22.     MyName: string;
  23.   public
  24.     Value: Variant;
  25.     Reference: TObject;
  26.     property Name: string read MyName;
  27.     constructor Create(ThisName: string);
  28.   end;
  29.  
  30.   { TResultQueue }
  31.  
  32.   TResultQueue = class(TPasMPUnboundedQueue<TRunResult>);
  33.  
  34.   { TThreadFunction }
  35.  
  36.   TThreadFunction = function(ThisThread: TRunFunction; Para1, Para2: Variant;
  37.     Para3: TObject): TRunResult of object;
  38.  
  39.   { TRunFunction }
  40.  
  41.   TRunFunction = class(TThread)
  42.   protected
  43.     MyName: string;
  44.     MyQueue: TResultQueue;
  45.     MyFunction: TThreadFunction;
  46.     MyPara1: Variant;
  47.     MyPara2: Variant;
  48.     MyPara3: TObject;
  49.     procedure Execute; override;
  50.   public
  51.     constructor Create(ThisName: string; ThisQueue: TResultQueue;
  52.       ThisFunction: TThreadFunction; Para1, Para2: Variant; Para3: TObject = nil);
  53.     function PostMessage(ThisValue: Variant; ThisReference: TObject = nil):
  54.       Boolean;
  55.   end;
  56.  
  57.  
  58. implementation
  59.  
  60. { TRunResult }
  61.  
  62. constructor TRunResult.Create(ThisName: string);
  63. begin
  64.   MyName := ThisName;
  65.   Value := Null;
  66.   Reference := nil;
  67. end;
  68.  
  69. { TRunFunction }
  70.  
  71. procedure TRunFunction.Execute;
  72. var
  73.   r: TRunResult;
  74. begin
  75.   if Assigned(MyFunction) then
  76.   begin
  77.     r := MyFunction(Self, MyPara1, MyPara2, MyPara3);
  78.     if Assigned(MyQueue) then
  79.       MyQueue.Enqueue(r);
  80.   end;
  81. end;
  82.  
  83. constructor TRunFunction.Create(ThisName: string; ThisQueue: TResultQueue;
  84.   ThisFunction: TThreadFunction; Para1, Para2: Variant; Para3: TObject);
  85. begin
  86.   inherited Create(True);
  87.  
  88.   FreeOnTerminate := True;
  89.   MyName := ThisName;
  90.   MyQueue := ThisQueue;
  91.   MyFunction := ThisFunction;
  92.   MyPara1 := Para1;
  93.   MyPara2 := Para2;
  94.   MyPara3 := Para3;
  95.  
  96.   Start;
  97. end;
  98.  
  99. function TRunFunction.PostMessage(ThisValue: Variant; ThisReference: TObject
  100.   ): Boolean;
  101. var
  102.   r: TRunResult;
  103. begin
  104.   Result := False;
  105.  
  106.   if Assigned(MyQueue) then
  107.   begin
  108.     r := TRunResult.Create(MyName);
  109.     r.Value := ThisValue;
  110.     r.Reference := ThisReference;
  111.     MyQueue.Enqueue(r);
  112.     Result := True;
  113.   end;
  114. end;
  115.  
  116. 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.

 

TinyPortal © 2005-2018