Arsip: Transformasi ke multi thread

 
user image
more 12 years ago

pebbie

guys, gw lagi ngoprek2 multithreading di delphi 7. kyknya (AFAIK) blum pernah ada yang bahas yang mau gw tanya. mohon bantuannya yah. jadi gini, gw punya atribut bertipe array of integer di kelas tform1. sebut saja
...
public
  arr : array of integer;
...
gw punya prosedur yang isinya mengubah tiap elemen di array (asumsi sudah diinisialisasi panjang dan nilai awalnya (misal 0)).
procedure TForm1.Button1Click(Sender: TObject);
var
  i : integer;
begin
  for i := 0 to high(arr) do
    arr[i] := arr[i] + 1; 
end;
gw mo bikin kelas turunan tthread (sebut saja TMyThread) yang isi method execute-nya (arr[i] := arr[i] + 1) dari prosedur di atas. sejumlah (n) objek TMythread dipegang di Form1. nah, pertanyaannya.. gimana caranya mendelegasikan n thread ini supaya menggantikan fungsi button1click? NB:n mungkin tidak sama dengan panjang array arr, kalau bisa sejumlah thread ini hanya perlu di-create sekali (sebelum 'for') dan tetap hidup sampai tugas selesai NB(lagi):bwt yang bingung gw mau ngapain, gw lagi pengen bikin imitasi dari paralelisasi for (#pragma omp parallel for) di OpenMP (atau Parallel Extension di .NET 2008) ke Delphi 7 thx b4
user image
more 12 years ago

asiyrob

coba bantu..walaupun ga' begitu ngerti?? dari pengamatan sekilas, maka ane mendapat hipotesis bahwa= 1. program akan error/debug ketika button1 diklik terus menerus (silahkan coba)!! 2. gunakan function (silahakan berexplorasi)!! 3. program harus dibuat realtime, bisa gunakan timer/msg dari window maaf klo hipotesis ane salah.. :mrgreen: :mrgreen:
user image
more 12 years ago

pebbie

Gw berhasil bikin tapi ada masalah.. ini file Unit2.pas isinya turunan kelas TThread
unit Unit2;
interface
uses
  Classes, Windows, SysUtils;
type
  TThreadState = (tsRunning, tsIdle, tsDone);
  TArrElmtModifier = class(TThread)
  private
    { Private declarations }
    FX, FY, FID: integer;
    FState : TThreadState;
  protected
    procedure Execute; override;
    procedure NotifyStart;
    procedure NotifyDone;
  public
    constructor Create(AID:integer);
    procedure Run;
    procedure Done;
    property X : integer read FX write FX;
    property Y : integer read FY write FY;
    property ID : integer read FID write FID;
    property State : TThreadState read FState write FState;
  end;
implementation
uses Unit1;
{ TArrElmtModifier }
constructor TArrElmtModifier.Create(AID:integer);
begin
  inherited Create(false);
  FID := AID;
  X := 0;
  Y := 0;
  State := tsIdle;
  self.FreeOnTerminate := false;
end;
procedure TArrElmtModifier.Done;
begin
  FState := tsDone;
end;
procedure TArrElmtModifier.Execute;
begin
  { Place thread code here }
  while (FState<>tsDone) do begin
    if (FState=tsRunning) then begin
      { Do Thread Task here }
      Form1.arr[Y][X] := Form1.arr[Y][X] + 10;
      NotifyDone;
      { Notify when task done }
    end;
    sleep(1);
  end;
end;
procedure TArrElmtModifier.NotifyDone;
begin
  Form1.AcceptDone(FID);
  State := tsIdle;
end;
procedure TArrElmtModifier.NotifyStart;
begin
  Form1.Memo1.Lines.Add('Thread#'+inttostr(FID)+'started');
end;
procedure TArrElmtModifier.Run;
begin
  State := tsRunning;
end;
end.
dan ini file Unit1.pas yang menyimpan array (arr). prosedur Button1Click merupakan acuan (dijalankan secara sekuensial tanpa threading) sedangkan Button2Click adalah versi multithreading. pekerjaan utamanya adalah menambahkan tiap elemen array arr dengan 10.
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Unit2, StdCtrls, Spin;
type
  TForm1 = class(TForm)
    Memo1: TMemo;
    SpinEdit1: TSpinEdit;
    Button2: TButton;
    Label1: TLabel;
    Label2: TLabel;
    SpinEdit2: TSpinEdit;
    Button1: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    nthreads : integer;
    threadflags : array of boolean;
    threads : array of TArrElmtModifier;
    arr : array of array of integer;
    tq : integer;
    procedure Prepare;
    procedure DispatchThreads;
    procedure AcceptDone(idx:integer);
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.AcceptDone(idx: integer);
begin
  threadflags[idx] := false;
  //memo1.lines.Add('done#'+inttostr(idx));
end;
procedure TForm1.DispatchThreads;
var
  i, j, k : integer;
  busy : boolean;
  tmp : tstrings;
  start, finish : longint;
begin
  Memo1.Lines.Clear;
  start := GetTickCount;
  
  { ordered scheduling }
  for j := 0 to high(arr) do
    for i := 0 to high(arr[j]) do begin
      { schedule iteration(i,j) }
      busy := true;
      repeat
        k := tq; //GetNextAvailableThread
        //if not threadflags[k] then begin
        if threads[k].State = tsIdle then begin
          threadflags[k] := true;
          //memo1.lines.add(format('dispatch (%d,%d) to thread#%d',[i,j,k]));
          threads[k].X := i;
          threads[k].Y := j;
          threads[k].Run;
          busy := false;
          break;
        end;
        tq := (tq + 1) mod length(threads);
        Application.ProcessMessages;
      until not busy;
    end;
    
  { barrier, wait until all task finished }
  repeat
    busy := false;
    for k := 0 to high(threads) do begin
      if threadflags[k] then begin
        busy := true;
        break;
      end;
    end;
    Application.ProcessMessages;
  until not busy;
  finish := GetTickCount;
  { clean up threads }
  for i := 0 to high(threads) do
    threads[i].State := tsDone;
  { display changes }
  tmp := TStringlist.Create;
  for j := 0 to high(arr) do begin
    tmp.Clear;
    for i := 0 to high(arr[j]) do begin
      tmp.add(inttostr(arr[j][i]));
    end;
    memo1.Lines.add(tmp.CommaText);
  end;
  Memo1.Lines.Add('Done in '+inttostr(finish-start)+' ms');
  tmp.Free;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
  i : integer;
begin
  Prepare;
  nthreads := SpinEdit1.Value;
  setlength(threadflags, nthreads);
  setlength(threads, nthreads);
  for i := 0 to high(threads) do begin
    threadflags[i] := false;
    threads[i] := TArrElmtModifier.Create(i);
  end;
  DispatchThreads;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
  i, j, k : integer;
  start, finish : cardinal;
  tmp : TStrings;
begin
  Prepare;
  Memo1.Lines.Clear;
  start := GetTickCount;
  { ordered scheduling }
  for j := 0 to high(arr) do
    for i := 0 to high(arr[j]) do begin
      arr[j][i] := arr[j][i] + 10;
    end;
  finish := GetTickCount;

  { display changes }
  tmp := TStringlist.Create;
  for j := 0 to high(arr) do begin
    tmp.Clear;
    for i := 0 to high(arr[j]) do begin
      tmp.add(inttostr(arr[j][i]));
    end;
    memo1.Lines.add(tmp.CommaText);
  end;
  Memo1.Lines.Add('Done in '+inttostr(finish-start)+' ms');
  tmp.Free;
end;
procedure TForm1.Prepare;
var
  i,n : integer;
begin
  n := SpinEdit2.Value;
  if length(arr)>0 then
    for i := 0 to high(arr) do
      setlength(arr[i], 0);
  setlength(arr, n);
  for i := 0 to high(arr) do
    setlength(arr[i], n);
  tq := 0;
end;
end.
kesimpulannya, kode yang multithread itu berjalan lebih lambat daripada yang sekuensial. memang sih operasi yang diparalelin itu terlalu sederhana sehingga overhead untuk komunikasi dan delegasi thread terlalu besar. - kalo diasumsikan task untuk tiap thread cukup kompleks secara komputasi, apa mungkin mekanisme delegasi multithread ini bisa dioptimasi lagi? - apa cara yang gw pake terlalu mahal di kelas turunan TThread?
user image
more 12 years ago

DelphiExpert

1. Manage thread dalam sebuah List; kemudian utk controlling anda dapat melakukan perulangan sebanyak thread-count. thread[0].resume, suspend etc. 2. dalam execute, jika pekerjaan selesai, thread harus men-suspend dirinya sendiri utk kemudian dibangunkan dari thread lain (resume) apabila ada data / pekerjaan baru
user image
more 12 years ago

DelphiExpert

wah, komen saya diatas harusnya uda terpost beberapa menit yg lalu... perasaan udah tonjok tombol submit, kok belum terkirim... :mrgreen:
user image
more 12 years ago

DelphiExpert

Parallel programming seharusnya menghasilkan kinerja lebih cepat daripada dikerjakan sekuensial. artinya apa? artinya ada yg salah dalam implementasinya. banyak hal misal: salah design, optimasi kode, synchronisasi yg kurang tepat (to many locking) dll. Hal ini sangat berpengaruh pada hasil akhir :)
user image
more 12 years ago

pebbie

bro DE, yang ke 1 udah diimplementasi pake array (threads di Form1), yang ke 2 udah pake property State di kelas TArrElmtModifier (tipe TThreadState {tsIdle untuk suspend, tsDone untuk otomatis terminate}) di kode di atas nggak ada locking, bahkan notifydone pun nggak di synchronize biar cepet. programnya sih udah cukup menggambarkan peningkatan (dengan acuan 1 thread).. maka penambahan n thread akan mempercepat eksekusi sebesar tn/t1 tapi tetap saja kalo kode yang sekuensial itu pas diukur waktunya 0 ms. :( apa memang contoh kasusnya nggak relevan untuk parallel programming yah? karena secara sekuensial pun udah cukup cepat..
artinya ada yg salah dalam implementasinya. banyak hal misal: salah design, optimasi kode, synchronisasi yg kurang tepat (to many locking) dll.
kalo menurut bro DE, yang salah dari kode di atas di mana ya kira-kira?
user image
more 12 years ago

mat_koder

Sumbang saran dari saya: Sekalipun dalam setiap thread , main tasknya "computation intensive: , saya nyaranin bikin tambahan satu atau dua thread saja ( disesuaikan dngan jumlah core CPU yg ada dlm mesin tsb). Main thread me-manage GUI dan ngontrol thread tsb. Windows kan pake konsep preemptive multitasking ( setiap thread ngga harus diberi slice waktu yg sama) , jadi ngga selalu berarti makin banyak thread makin banyak jatah persentase CPU cycle. Emang jika bersamaan dan bersaing dengan aplikasi laen yg juga computation intensive, konsep makin banyak thread makin baik mungkin akan berhasil, namun untuk pemakaian umum rasanya engga-lah. Yang jadi pertanyaan tentunya adalah apakah Delphi compiler sudah cukup smart untuk memisahkan ( mendistribusikan) masing-masing thread yg di-create oleh aplikasi supaya dikerjakan oleh CPU core yg berbeda pada mesin multi core. Ada yg tahu mengenai hal ini?
user image
more 12 years ago

pebbie

ternyata ketika dijalankan di luar IDE, berjalan jauh lebih cepat sehingga bisa sebanding dengan eksekusi sekuensial. laporannya sudah saya tulis di blog saya. kesimpulannya, eksperimen saya di atas bisa dibilang cukup berhasil. setahu saya preemptive multi-tasking hanya berlaku pada proses, bukan thread. dan hipotesis saya bahwa tiap thread dalam suatu proses dialokasikan time-slice yang sama dan proses yang memiliki beberapa thread memiliki prioritas untuk preempted yang lebih kecil. Buktinya adalah program yang memanfaatkan thread di mesin yang memiliki lebih dari 1 core dalam 1 prosesor (multicore) ketika dilihat dengan task manager maka CPU Usage-nya bisa mencapai 100% sedangkan jika diimplementasi tanpa threading maka maksimum CPU Usage-nya adalah 50 % (untuk dual core CPU). urusan distribusi thread ini saya juga masih belum paham apakah ini tanggung jawab compiler atau justru runtime environment yang dalam hal ini adalah operating system. ada yang punya informasi yang lebih akurat?
user image
more 12 years ago

pebbie

oya, lupa bilang terima kasih sama bung mat koder. secara otomatis/default pengelolaan GUI sudah memiliki satu thread sendiri sehingga thread lainnya merupakan tambahan dari thread ini (TApplication sepertinya). di eksperimen saya, dengan menggunakan 2 thread, ketika dilihat menggunakan task manager, thread untuk proses ybs tercantum sebagai 3 thread.
more ...
  • Pages:
  • 1
  • 2
Share to

Random Topic

Local Business Directory, Search Engine Submission & SEO Tools FreeWebSubmission.com SonicRun.com