線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:11553
推到 Plurk!
推到 Facebook!

我使用多線程之後為什麼程式仍然是獨佔CPU?

答題得分者是:小傑克
bluesum
一般會員


發表:3
回覆:11
積分:2
註冊:2009-05-09

發送簡訊給我
#1 引用回覆 回覆 發表時間:2009-05-09 23:10:48 IP:203.83.xxx.xxx 訂閱
各位好

我剛學習寫muti thread,
我己看過 http://delphi.ktop.com.tw/board.php?cid=168&fid=923&tid=93670
但是我使用多線程之後為什麼程式仍然是獨佔CPU
我的來源碼 :
http://home.i-cable.com/wu/testduel.zip
測試雙綫程在 TestduelbuttonClick.
不知道哪里出錯了?
多謝各位先

編輯記錄
bluesum 重新編輯於 2009-05-09 23:11:22, 註解 無‧
bluesum 重新編輯於 2009-05-09 23:16:38, 註解 無‧
chih_kuan
中階會員


發表:38
回覆:82
積分:54
註冊:2003-02-20

發送簡訊給我
#2 引用回覆 回覆 發表時間:2009-05-11 11:39:48 IP:61.59.xxx.xxx 訂閱
請在 Execute  程序中..加上一行 
Sleep(1);
------
叔叔有練過,初學者不要學。
bluesum
一般會員


發表:3
回覆:11
積分:2
註冊:2009-05-09

發送簡訊給我
#3 引用回覆 回覆 發表時間:2009-05-11 20:18:43 IP:203.83.xxx.xxx 訂閱

===================引 用 chih_kuan 文 章===================
請在 Execute 程序中..加上一行
Sleep(1);

[code delphi]
procedure TAIThrd.Execute;
var a,b:integer;
begin
// if not assigned(pointer(Fthreadno)) then
// Fthreadno:=1;
// if not assigned(pointer(Fcancut)) then
// Fcancut :=True;
Sleep(1); // <--加在這裏 ? 依然唔得.
strtoboard;
if Fthreadno = 1 then
Fthinkstep:=ThinkNumber(AIboard,FAIcolor,FRealdepth)
else
Fthinkstep:=ThinkNumber(AIboard,FAIcolor,FRealdepth-1);
........
[/code]
編輯記錄
bluesum 重新編輯於 2009-05-11 20:19:28, 註解 無‧
bluesum
一般會員


發表:3
回覆:11
積分:2
註冊:2009-05-09

發送簡訊給我
#4 引用回覆 回覆 發表時間:2009-05-11 20:40:04 IP:203.83.xxx.xxx 訂閱
我不知道為何只有這樣測試質數才沒問題
[code delphi]
unit PrimeForm;
// http://www.pergolesi.demon.co.uk/prog/threads/Ch2.html
interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,SyncObjs;

type
TPrimeNotifyEvent = procedure(const TestNum:string;const Realprime: Boolean) of object;
TPrimeThrd = class(TThread)
private
FTestNumber: integer;
FPrimeResult: boolean;
FPrimeNotifyEvent: TPrimeNotifyEvent;
protected
// function IsPrime: boolean;
procedure IsPrime;
procedure Execute; override;
procedure Call;
public
property TestNumber: integer write FTestNumber;
property PrimeResult: boolean read FPrimeResult;
property PrimeNotifyEvent :TPrimeNotifyEvent read FPrimeNotifyEvent write FPrimeNotifyEvent;
// Published
end;


type
TPrimeFrm = class(TForm)
NumEdit: TEdit;
Button2: TButton;
Memo1: TMemo;
procedure OnPrimeNotifyEvent(const Testnumber:string;const Realprime:boolean);
procedure DoubleThread(const num:integer);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
Listbox1:TStringList;
LockLIST:TCriticalSection;
uncounted:integer;
testa,testb:boolean;
{ Private declarations }
public
rectime:Tdatetime;
{ Public declarations }
end;
var
PrimeFrm: TPrimeFrm;
implementation
//uses PrimeThread;
{$R *.dfm}
Procedure TPrimeThrd.IsPrime;
var
iter: integer;
begin
FPrimeResult := True;
if FTestNumber < 0 then
begin
FPrimeResult := false;
exit;
end;
if FTestNumber <= 2 then
exit;
for iter := 2 to FTestNumber - 1 do
begin
if (FTestNumber mod iter) = 0 then
begin
FPrimeResult := False;
exit;
{exit;}
end;
end;
end;
procedure TPrimeThrd.Execute;
//var a:boolean;
begin
IsPrime;
if assigned(PrimeNotifyEvent) then
Synchronize(Call);
end;
procedure TPrimeThrd.Call;
begin
PrimeNotifyEvent(intTostr(FTestNumber),FPrimeResult);
end;

procedure TPrimeFrm.OnPrimeNotifyEvent(const Testnumber:string;const Realprime:boolean);
var a:integer;
begin
LockList.Acquire;
memo1.lines.add(Testnumber ' ' BoolToStr(Realprime,True));
a:= 123456789-strToint(Testnumber)-90;
Listbox1[a 90] := 'y';
if a = -1 then
begin
if testb then
begin
memo1.lines.add('finish');
end;
testa := true;
LockList.Release;
exit;
end;
if a = 0 then
begin
if testa then
begin
memo1.lines.add('finish');
end;
testb := true;
LockList.Release;
exit;
end;
a:= listbox1.IndexOf(' ');
a:= 123456789-a;
// a:=strtoint(Testnumber)-2;
DoubleThread(a);
end;
procedure TPrimeFrm.DoubleThread(const num:integer);
var NewThread: TPrimeThrd;
begin
NewThread := TPrimeThrd.Create(True);
NewThread.FreeOnTerminate := True;
NewThread.TestNumber := num;
NewThread.PrimeNotifyEvent := OnPrimeNotifyEvent;
NewThread.Resume;
end;

procedure TPrimeFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Listbox1.Free;
LockLIST.Destroy;
end;
procedure TPrimeFrm.FormCreate(Sender: TObject);
begin
Listbox1:=Tstringlist.Create;
LockLIST:=TCriticalSection.Create;
end;
procedure TPrimeFrm.Button2Click(Sender: TObject);
var a:integer;
begin
// Method3a:=False;
// Method3b:=False;
memo1.Clear;
// uncounted:= 90;
listbox1.Clear;
for a:= 1 to 100 do
listbox1.Add(' ');
DoubleThread(123456789);
DoubleThread(123456788);
end;
end.

[/code]
小傑克
資深會員


發表:5
回覆:209
積分:357
註冊:2009-02-16

發送簡訊給我
#5 引用回覆 回覆 發表時間:2009-05-12 20:02:46 IP:59.115.xxx.xxx 訂閱
http://delphi.ktop.com.tw/board.php?cid=30&fid=1498&tid=97825

剛好這篇討論中我有寫個測試, 你可以用簡單的程式感受一下差別在哪邊
------
額有朝天骨,眼中有靈光
bluesum
一般會員


發表:3
回覆:11
積分:2
註冊:2009-05-09

發送簡訊給我
#6 引用回覆 回覆 發表時間:2009-05-13 00:26:59 IP:203.83.xxx.xxx 訂閱
我的目的是想雙核心cpu的同時盡力做野
===================引 用 小傑克 文 章===================
http://delphi.ktop.com.tw/board.php?cid=30&fid=1498&tid=97825

剛好這篇討論中我有寫個測試, 你可以用簡單的程式感受一下差別在哪邊
小傑克
資深會員


發表:5
回覆:209
積分:357
註冊:2009-02-16

發送簡訊給我
#7 引用回覆 回覆 發表時間:2009-05-13 03:09:34 IP:59.115.xxx.xxx 訂閱
就我的理解是這樣,mutli- thread 跟雙cpu 是沒關聯的, 雙cpu運用 是由系統分配, 除非你程式中指定cpu
http://delphi.ktop.com.tw/board.php?cid=168&fid=923&tid=90685 有提到,但是我沒雙cpu,也沒這樣試過

就我的理解在mutli-thread程式中, 就像賣電影票的窗口和外面排隊的人群, 有沒有用Synchronize() 對於系統 (os), 就像有沒有警察在維持排隊的秩序, 當你用Synchronize時, 外面人雖然排很多,但是警察(delphi)會維持秩序確保只有一排隊伍, 好處是Synchronize 由delphi底層幫你做memory control 的事,例如thread共用golbal 變數, 或是某些VCL, 壞處是ap不會去壓榨os , 而當沒用Synchronize時 , 脫序的群眾一擁而上去捶打賣票的窗口(os), 這時os 如果有辦法的話, 也許會多開兩個窗口一起賣票, 但這決定權, 是在os 上,不是ap決定的, 如果售票小姐只有一個, 同時開十個窗口(10-thread waiting) 也沒用,只是一個小姐跑來跑去而已,但至少這個小姐會很忙,不會一邊看報紙一邊吃便當一邊講手機一邊賣票

我注意到你在thread 的execute 中用Synchronize(call) 而在call 這個function 中做PrimeNotifyEvent , 而PrimeNotifyEvent 中你又使用LockList , 根據說明 , LockList 是通知os 由os 來確保只有一個thread 在執行.....我不知道LockList 在多cpu機器中具體的運作是怎樣, 但我猜LockList 實現的方法還是讓Lock / unlock 期間的程式同一時間只有一個在執行

我之前貼的那個小測試程式,主要是測試 Synchronize (我有remark 起來), Application.ProcessMessages, sleep(1) 這三個,這三個對結果都是有影響的,你可以試試沒有Synchronize 沒有sleep的時候的狀況, 再加大一點cpu忙碌程度試試看(比如跑個1 - 50000萬空for loop的)
------
額有朝天骨,眼中有靈光
編輯記錄
小傑克 重新編輯於 2009-05-13 03:18:13, 註解 無‧
bluesum
一般會員


發表:3
回覆:11
積分:2
註冊:2009-05-09

發送簡訊給我
#8 引用回覆 回覆 發表時間:2009-05-13 07:41:02 IP:203.83.xxx.xxx 訂閱

===================引 用 小傑克 文 章===================
就我的理解是這樣,mutli- thread 跟雙cpu 是沒關聯的, 雙cpu運用 是由系統分配, 除非你程式中指定cpu
http://delphi.ktop.com.tw/board.php?cid=168&fid=923&tid=90685 有提到,但是我沒雙cpu,也沒這樣試過

===================引 用 harpist 文 章===================
C Builder 不支援...

Visual C 2005 OpenMP
http://msdn2.microsoft.com/en-us/library/tt15eb9t(VS.80).aspx
http://www.openmp.org/drupal/

我答:我放棄了.
===================引 用 小傑克 文 章===================
就我的理解在mutli-thread程式中, 就像賣電影票的窗口和外面排隊的人群, 有沒有用Synchronize() 對於系統 (os), 就像有沒有警察在維持排隊的秩序, 當你用Synchronize時, 外面人雖然排很多,但是警察(delphi)會維持秩序確保只有一排隊伍, 好處是Synchronize 由delphi底層幫你做memory control 的事,例如thread共用golbal 變數, 或是某些VCL, 壞處是ap不會去壓榨os , 而當沒用Synchronize時 , 脫序的群眾一擁而上去捶打賣票的窗口(os), 這時os 如果有辦法的話, 也許會多開兩個窗口一起賣票, 但這決定權, 是在os 上,不是ap決定的, 如果售票小姐只有一個, 同時開十個窗口(10-thread waiting) 也沒用,只是一個小姐跑來跑去而已,但至少這個小姐會很忙,不會一邊看報紙一邊吃便當一邊講手機一邊賣票

我答:可以的,用兩架飛機就有兩個小姐,見最後我答的那段

===================引 用 小傑克 文 章===================

我注意到你在thread 的execute 中用Synchronize(call) 而在call 這個function 中做PrimeNotifyEvent , 而PrimeNotifyEvent 中你又使用LockList , 根據說明 , LockList 是通知os 由os 來確保只有一個thread 在執行.....我不知道LockList 在多cpu機器中具體的運作是怎樣, 但我猜LockList 實現的方法還是讓Lock / unlock 期間的程式同一時間只有一個在執行

我答:我刪了Synchronize和LockList 也不行

===================引 用 小傑克 文 章===================
我之前貼的那個小測試程式,主要是測試 Synchronize (我有remark 起來), Application.ProcessMessages, sleep(1) 這三個,這三個對結果都是有影響的,你可以試試沒有Synchronize 沒有sleep的時候的狀況, 再加大一點cpu忙碌程度試試看(比如跑個1 - 50000萬空for loop的)

我答:連50% cpu也不到

結語:唯有將 aiThread 做成 Console 程式,外殼產生兩個 JVCL的TJvCreateProcess 控件,那個控件執行Console 程式,輸入輸出會轉到外殼.
如果三日沒有更好的解決辦法我就結案

編輯記錄
bluesum 重新編輯於 2009-05-13 12:44:36, 註解 影射->映射‧
bluesum 重新編輯於 2009-05-13 12:49:23, 註解 映射也寫錯‧
RootKit
資深會員


發表:16
回覆:358
積分:419
註冊:2008-01-02

發送簡訊給我
#9 引用回覆 回覆 發表時間:2009-05-13 23:35:06 IP:122.126.xxx.xxx 訂閱
能不獨佔CPU 才見鬼!
請認真想一下 MultiThread 的精髓是什麼 !?

有時候需要同步時,可讓出短暫的CPU控制權,將 CriticalSection 效率提高。
johnlp
一般會員


發表:2
回覆:13
積分:8
註冊:2004-10-31

發送簡訊給我
#10 引用回覆 回覆 發表時間:2009-05-15 23:48:13 IP:115.81.xxx.xxx 未訂閱
調整thread priority
bluesum
一般會員


發表:3
回覆:11
積分:2
註冊:2009-05-09

發送簡訊給我
#11 引用回覆 回覆 發表時間:2009-05-16 06:16:46 IP:203.83.xxx.xxx 訂閱

===================引 用 johnlp 文 章===================
調整thread priority


[code delphi]
procedure TForm1.TestduelbuttonClick(Sender: TObject);
var NewThread:TAIThrd;anotherthread:TAIThrd;
begin
AiListBox.Clear;
NewThread:=TAIThrd.Create(true);
...
anotherthread.Resume;
Application.ProcessMessages;
sleep(500);
NewThread.Priority := tpHighest;
anotherthread.Priority:=tpHighest;
end;

[/code]
沒用
bluesum
一般會員


發表:3
回覆:11
積分:2
註冊:2009-05-09

發送簡訊給我
#12 引用回覆 回覆 發表時間:2022-04-26 06:00:50 IP:155.137.xxx.xxx 訂閱
經過很多年發現用 lazarus 解決
https://github.com/sum2012/sum-gnu-anti-Reversi-lazarus-windows
系統時間:2024-11-21 16:49:44
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!