Recent

Author Topic: Multi Threading  (Read 6820 times)

emjtech

  • New Member
  • *
  • Posts: 28
    • Global R&D ltd
Multi Threading
« on: February 13, 2019, 07:13:38 pm »
Hi
I do experience with Pascal, but never did multithreading.
I want to do a simple multithreaded program as follows:
1-Program runs normally accessing a very fast hardware,
   It has 2 Arrays predefined .
   It fills Array1 with values from the hardware
2-When the Array1 reach a predefined limit it
   - starts a secondary thread that open a file and save Array1 to the file
   - while the secondary thread is working it switches to Array2 and it fills Array2 with values from the hardware
   - in the meantime the secondary thread finishes the file, it closes it and goes to sleep
3-and so on an on switching between Arrays.

I so some tutorials how to define a thread but is very unclear to me, can someone guide me to a solucion? or point me to a good tutorial?
Thanks
Thanks
Eli Jacob

mr-highball

  • Full Member
  • ***
  • Posts: 233
    • Highball Github
Re: Multi Threading
« Reply #1 on: February 13, 2019, 08:14:13 pm »

asdf121

  • New Member
  • *
  • Posts: 35
Re: Multi Threading
« Reply #2 on: February 13, 2019, 08:23:41 pm »
Hey,
you just have to create a class which inherits from TThread and then overwrite the Execute method with the stuff you want to execute.
When you reach your limit you create another TThread with a different Execute method to save infos to a file and use automatic freeing it when it's done. In your other worker thread you can then check if it's variable is nil and then copy content from array2 back to array1 and write into it until it reaches the limit again. That's a simple and not bullet proof version but should work.
You could also use some Event stuff and locking, there are many ways to solve this task.  ;)
Just google about threads, there are many examples for this in the www:
http://wiki.lazarus.freepascal.org/Multithreaded_Application_Tutorial

« Last Edit: February 13, 2019, 08:25:37 pm by asdf121 »

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Multi Threading
« Reply #3 on: February 13, 2019, 08:39:29 pm »
Take a look at the futures implementation in https://github.com/avk959/LGenerics

kcandrews

  • Jr. Member
  • **
  • Posts: 50
Re: Multi Threading
« Reply #4 on: February 13, 2019, 09:21:10 pm »
When you need it and are past an initial multi-thread experience and want to take advantage of your likely multi-core processor using a "pool" of threads, check out the Lazarus package, MultiThreadProcsLaz 1.2.1. 

I found it very useful to do a lot of parameter variation on big multi-year financial backtests :-)

garlar27

  • Hero Member
  • *****
  • Posts: 652
Re: Multi Threading
« Reply #5 on: February 13, 2019, 10:06:25 pm »
I want to do a simple multithreaded program as follows:
1-Program runs normally accessing a very fast hardware,
   It has 2 Arrays predefined .
   It fills Array1 with values from the hardware
2-When the Array1 reach a predefined limit it
   - starts a secondary thread that open a file and save Array1 to the file
   - while the secondary thread is working it switches to Array2 and it fills Array2 with values from the hardware
   - in the meantime the secondary thread finishes the file, it closes it and goes to sleep
3-and so on an on switching between Arrays.
Once I did something like that (a double buffer) though I didn't used threads because data input wasn't that fast. The other difference was that I used a timer instead of a size limit.
For what you need, is better to read the tutorial asdf121 pointed. Pay attention to the use of critical zone waiting for threads and messages between threads.
There's also a PDF (Threads are Evil or Thread is Evil) made by some people of MIT which explain very well the problems of multi threading.-

sash

  • Sr. Member
  • ****
  • Posts: 366
Re: Multi Threading
« Reply #6 on: February 13, 2019, 10:40:52 pm »
Aside from Threads (and CriticalSections, RTLEvents), if your data is of serial/stream nature, it looks like instead of 2 arrays you need a ring-buffer queue:
  - 1st Thread reads incoming data, enqueues it and signals with RTLEvent,
  - 2nd Thread waits for data ready event, and once ready dequeues and writes to a file, and so on.
« Last Edit: February 13, 2019, 10:44:15 pm by sash »
Lazarus 2.0.10 FPC 3.2.0 x86_64-linux-gtk2 @ Ubuntu 20.04 XFCE

mangakissa

  • Hero Member
  • *****
  • Posts: 1131
Re: Multi Threading
« Reply #7 on: February 14, 2019, 08:51:21 am »
Another question. How do you manage it now? Is your application very slow? Does this procedure come very often of occasionally?

It's nice to have threads working, but only when it is meaningful.
Lazarus 2.06 (64b) / FPC 3.0.4 / Windows 10
stucked on Delphi 10.3.1

emjtech

  • New Member
  • *
  • Posts: 28
    • Global R&D ltd
Re: Multi Threading
« Reply #8 on: February 14, 2019, 09:29:08 am »
Hi
Got this morning with a lot of replies, :-)
I will test them now
Thank you all !!
Thanks
Eli Jacob

emjtech

  • New Member
  • *
  • Posts: 28
    • Global R&D ltd
Re: Multi Threading
« Reply #9 on: February 17, 2019, 03:02:18 pm »
Hi
I tried but I didn't found a good solution.
The asynchronous solution doesn't work right for me since (it does what it means to do) it waits til the recording finish then writes 10 files with the same (last) data, instead of 10 files in parallel with the recording on a second core.
Follows a simplified code, maybe one of you can help me find a solution:

Var
     DataArray: Array of Array of Array of Word;
     evenodd:Integer;
     fileNumber:Integer;
     TotalLines:Integer;

procedure Save(totalLines)
Var s:String;
      T:Text;
      i:Integer;
begin
    inc(fileNumber);
    s:=IntToString(fileNumber)+'.txt';
    AssignFile(T,s);
    Rewrite(T);
    for  i:=0 to totalLines do begin
       s:='';
       for j:=0 to 10 do
          s:=ConvertDatatoText(DataArray[evenodd,i,j];
    end;
    WriteLn(T,s);
    CloseFile(T);
end;

procedure RecordHardware;
Var
     i,line:Integer;
begin
   setlength DataArray(2,1000000,11);
   repeat
       for i:=0 to do
          DataArray[evenodd,line,i]:=readHW(i);
       inc(line);
       if line>=TotalLines then begin
            change(evenodd);
            Save(line);   //<----------- This should be done on a separate thread without slowing the Hardware reading
                               // (on a separated core - there are 4 cores on Raspberry Pi 3B+)
            line:=0;
       end;
   until HardwareStop;
end;

Can someone help me?
Thanks
Eli Jacob

mangakissa

  • Hero Member
  • *****
  • Posts: 1131
Re: Multi Threading
« Reply #10 on: February 17, 2019, 10:25:28 pm »
This is not all.
- What length has YotalLines
- 'for i:=0 to do' is not working
- what is variable line doing if you have variable i
- what is Save(line actually doing with variable line.
- If RecordHardware is called again, the same filenumbers are used to save data

I tried to give yoa an good example, but this code doesn't work. Please make a demo or copy the right code.
Lazarus 2.06 (64b) / FPC 3.0.4 / Windows 10
stucked on Delphi 10.3.1

JimD

  • Jr. Member
  • **
  • Posts: 62
Re: Multi Threading
« Reply #11 on: February 17, 2019, 11:42:29 pm »

I have a couple of very easy examples with working demos here:
https://github.com/jasc2v8/LazUnits/tree/master/ThreadUnit

You should be able to adapt for your code.
Hope it helps. . .

mangakissa

  • Hero Member
  • *****
  • Posts: 1131
Re: Multi Threading
« Reply #12 on: February 18, 2019, 04:38:12 pm »
small example
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$H+}
  2.  
  3. interface
  4.  
  5. uses
  6.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  7.  
  8. type
  9.   TMyArray    = array[0..9] of array[0..999] of smallint;
  10.   TMySubArray = array[0..999] of smallint;
  11.  
  12.   TMsgEvent  = procedure(const aMsg : string) of object;
  13.  
  14.   { TMyThread }
  15.  
  16.   TMyThread = class(TThread)
  17.     fMySubArray : TMySubArray;
  18.     fFileNumber : integer;
  19.     fFileName   : string;
  20.   private
  21.     FOnProgress: TMsgEvent;
  22.     procedure DoProgress;
  23.   protected
  24.     procedure Execute; override;
  25.   public
  26.     property OnProgress: TMsgEvent read FOnProgress write FOnProgress;
  27.   end;
  28.  
  29.   { TForm1 }
  30.  
  31.   TForm1 = class(TForm)
  32.     Button1: TButton;
  33.     Memo1: TMemo;
  34.     procedure Button1Click(Sender: TObject);
  35.     procedure FormCreate(Sender: TObject);
  36.   private
  37.      fFilenumber : integer;
  38.      procedure DoMyProgress(const aMsg : string);
  39.      procedure fill;
  40.   end;
  41.  
  42. var
  43.   Form1: TForm1;
  44.  
  45. implementation
  46.  
  47. {$R *.lfm}
  48.  
  49. { TForm1 }
  50.  
  51. procedure TForm1.Button1Click(Sender: TObject);
  52. begin
  53.   fill;
  54.   memo1.lines.add('klaar');
  55. end;
  56.  
  57. procedure TForm1.fill;
  58. var FMyArray  : TMyArray;
  59.     index     : smallint;
  60.     subindex  : smallint;
  61.     MyThread  : TMyThread;
  62. begin
  63.   for index := low(fMyArray) to high(fMyArray) do
  64.   begin
  65.     for subindex := low(fMyArray[index]) to high(fMyArray[index]) do
  66.       fMyArray[index,subindex] := subindex;
  67.     fFilenumber := fFilenumber + 1;
  68.     MyThread  := TMyThread.create(true);
  69.     MyThread.fFileNumber := fFilenumber;
  70.     MyThread.fMySubArray := fMyArray[index];
  71.     MyThread.FreeOnTerminate := true;
  72.     MyThread.OnProgress := @DoMyProgress;
  73.     MyThread.Start;
  74.   end;
  75. end;
  76.  
  77. procedure TForm1.FormCreate(Sender: TObject);
  78. begin
  79.   fFilenumber := 0;
  80. end;
  81.  
  82. procedure TForm1.DoMyProgress(const aMsg : string);
  83. begin
  84.   memo1.lines.add(aMsg)
  85. end;
  86.  
  87. { TMyThread }
  88.  
  89. procedure TMyThread.Execute;
  90. var MyFile   : TextFile;
  91.     index    : integer;
  92. begin
  93.   ffilename := format('myfile_%.5d.txt',[fFilenumber]);
  94.   try
  95.     Assignfile(MyFile,ffilename);
  96.     rewrite(MyFile);
  97.     writeln(MyFile,fFilename);
  98.     for index := 0 to length(fMySubArray) - 1 do
  99.       system.Write(MyFile,fMySubArray[index]);
  100.   finally
  101.     system.close(MyFile);
  102.     synchronize(@doProgress)
  103.   end;
  104. end;
  105.  
  106. procedure TMyThread.DoProgress;
  107. begin
  108.   if Assigned(FOnProgress) then
  109.     FOnProgress(fFilename);
  110. end;
  111.  
  112. end.
  113.  
Lazarus 2.06 (64b) / FPC 3.0.4 / Windows 10
stucked on Delphi 10.3.1

emjtech

  • New Member
  • *
  • Posts: 28
    • Global R&D ltd
Re: Multi Threading
« Reply #13 on: February 20, 2019, 04:22:13 pm »
Thanks , I will try your example
Thanks
Eli Jacob

emjtech

  • New Member
  • *
  • Posts: 28
    • Global R&D ltd
Re: Multi Threading
« Reply #14 on: February 20, 2019, 04:26:08 pm »
Hi
Sorry is not real code, I only want to put some lines around the call to "Save(line);"
in order to make more clear what I need to do.
The point it that the call to "Save(line)" must return immediately and the code in Save(line) must be started immediately on a second core so the main routine does not wait.


This is not all.
- What length has YotalLines
- 'for i:=0 to do' is not working
- what is variable line doing if you have variable i
- what is Save(line actually doing with variable line.
- If RecordHardware is called again, the same filenumbers are used to save data

I tried to give yoa an good example, but this code doesn't work. Please make a demo or copy the right code.
Thanks
Eli Jacob

 

TinyPortal © 2005-2018