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

Variant Array 的快速複製?

答題得分者是:william
shaofu
高階會員


發表:5
回覆:136
積分:103
註冊:2003-01-07

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-05-12 11:50:09 IP:210.243.xxx.xxx 未訂閱
轉貼 Programmer 深度論壇的問題.. 我想不到較快的方法, 大家來討論看看 :P 原址: ================================ http://forum.vclxx.org/topic.php?TOPIC_ID=25539&FORUM_ID=8&CAT_ID=2&Topic_Title=variantªº§ֳt½ƻs?&Forum_Title=Pascal 內容: ================================ aryData : variant; aryNew : variant; 如果處理後aryData是一個內含2維variant陣列的variant變數 也就是aryData[0,0]至aryData[5,100]都有variant型態的資料 然後 aryNew:=VarArrayCreate([0,20],varVariant); 請問如果不用迴圈一一指定, 要如何快速將aryData[3,20]至aryData[3,50]快速複製到aryNew[0..20] ? 發表人 - shaofu 於 2003/05/12 14:03:31
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-05-12 12:35:38 IP:147.8.xxx.xxx 未訂閱
If the element types of the source is fixed (e.g. longint), you can calculate the address of the data needed and do a move, which should be much more faster.
type
    PVarArray = ^TVarArray;
    TVarArray = array[0..100] of variant;
var
    V,N: variant;
    i,j,t1,t2,t3,t4: integer;
    PV,PN: PVarArray;
    f: boolean;
begin
    V := VarArrayCreate([0,5,0,100],varVariant);
    for i := 0 to 5 do
        for j := 0 to 100 do
            V[i,j] := random;
    N := VarArrayCreate([0,30],varVariant);
    t1 := GetTickCount;
    for j := 1 to 10000 do // do 10000 times
        for i := 0 to 30 do
            N[i] := V[3,20 i];
    t2 := GetTickCount;
    VarClear(N);
    N := VarArrayCreate([0,30],varVariant);
    PV := VarArrayLock(V);
    PN := VarArrayLock(N);
    try
        t3 := GetTickCount;
        for j := 1 to 10000 do // do 10000 times
            for i := 0 to 30 do
                PN^[i] := V[3,20 i];
        t4 := GetTickCount;
    finally
        VarArrayUnLock(V);
        VarArrayUnLock(N);
    end;
    f := True;
    for i := 0 to 30 do
        f := f and (N[i]=V[3,i 20]);
    if f then
        ShowMessage(Format('1: %d%s2: %d',[t2-t1,#13   #10,t4-t3]))
    else
        ShowMessage('error');
end;
發表人 - william 於 2003/05/12 12:37:19
shaofu
高階會員


發表:5
回覆:136
積分:103
註冊:2003-01-07

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-05-12 13:22:51 IP:210.243.xxx.xxx 未訂閱
謝謝 william 兄的回應,  沒想到這樣寫在我電腦可以快到一倍以上  不過我原先就是想用 >
william
版主


發表:66
回覆:2535
積分:3048
註冊:2002-07-11

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-05-12 14:52:01 IP:147.8.xxx.xxx 未訂閱
Try it:  < class="code">type PVarArray = ^TVarArray; TVarArray = array[0..10000] of variant; var V,N: variant; i,j,t1,t2,t3,t4: integer; PV,PN: PVarArray; f: boolean; begin V := VarArrayCreate([0,5,0,100],varVariant); for i := 0 to 5 do for j := 0 to 100 do V[i,j] := random; N := VarArrayCreate([0,30],varVariant); t1 := GetTickCount; for j := 1 to 10000 do // do 10000 times for i := 0 to 30 do N[i] := V[3,20 i]; t2 := GetTickCount; VarClear(N); N := VarArrayCreate([0,30],varVariant); PV := VarArrayLock(V); PN := VarArrayLock(N); try t3 := GetTickCount; for j := 1 to 10000 do // do 10000 times for i := 0 to 30 do PN^[i] := PV^[3 (20 i)*6]; t4 := GetTickCount; finally VarArrayUnLock(V); VarArrayUnLock(N); end; f := True; for i := 0 to 30 do f := f and (N[i]=V[3,i 20]); if f then ShowMessage(Format('1: %d%s2: %d',[t2-t1,#13 #10,t4-t3])) else ShowMessage('error'); end;
jackkcg
站務副站長


發表:891
回覆:1050
積分:848
註冊:2002-03-23

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-05-12 15:32:07 IP:61.221.xxx.xxx 未訂閱
william 還真正是 利害的高手 配服配服 ********************************************************* 哈哈&兵燹 最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知 K.表Knowlege 知識,就是本站的標語:Open our mind to make knowledge together! 希望能大家敞開心胸,將知識寶庫結合一起
------
**********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好

Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind
shaofu
高階會員


發表:5
回覆:136
積分:103
註冊:2003-01-07

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-05-12 16:50:47 IP:210.243.xxx.xxx 未訂閱
真的可以了  分析這個問題, 我有兩個盲點 > > 感謝 > 發表人 -
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-05-14 06:02:37 IP:61.70.xxx.xxx 未訂閱
其實 Move 是可以用的 !!    move(aryData[0,0],aryData[5,100],sizeof(variant)*count)       基本上 variant 也是固定長度的!!也就是佔用等長度的記憶體空間。 所以
     V := VarArrayCreate([0,5,0,100],varVariant);
  for i := 0 to 5 do
   for j := 0 to 100 do
    V[i,j] := 999;      N := VarArrayCreate([0,30],varVariant);
  
  for i := 0 to 30 do
   N[i] := 333;      PV := VarArrayLock(V);
  PN := VarArrayLock(N);

  move(PV[0],PN[0],SizeOf(Variant)*5);    
你可以驗證 N 的前 5 筆資料,是 999 而不是原來的 333 所以如果是純粹複製,move 還是最快的 只是你要知道如何去變通!!
引言: 真的可以了 分析這個問題, 我有兩個盲點 > > 感謝 > 發表人 - >< face="Verdana, Arial, Helvetica">
shaofu
高階會員


發表:5
回覆:136
積分:103
註冊:2003-01-07

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-05-14 09:40:32 IP:210.243.xxx.xxx 未訂閱
Syntax 兄誤會我的意思了 < > > 為甚麼會這樣.. 我就不清楚了< > 發表人 -
shaofu
高階會員


發表:5
回覆:136
積分:103
註冊:2003-01-07

發送簡訊給我
#9 引用回覆 回覆 發表時間:2003-05-14 10:26:19 IP:210.243.xxx.xxx 未訂閱
可讀性高一點的寫法  < class="code"> type TVarArraySrc = array[0..100, 0..5] of variant; // 倒過來 Mapping TVarArrayDest = array[0..30] of variant; var V,N: variant; i,j,t1,t2,t3,t4: integer; PSrc: ^TVarArraySrc; PDest: ^TVarArrayDest; f: boolean; begin V := VarArrayCreate([0,5,0,100],varVariant); for i := 0 to 5 do for j := 0 to 100 do V[i,j] := i*100 j; N := VarArrayCreate([0,30],varVariant); t1 := GetTickCount; for j := 1 to 10000 do // do 10000 times for i := 0 to 30 do N[i] := V[3,20 i]; t2 := GetTickCount; VarClear(N); N := VarArrayCreate([0,30],varVariant); PSrc := VarArrayLock(V); PDest := VarArrayLock(N); try t3 := GetTickCount; for j := 1 to 10000 do // do 10000 times for i := 0 to 30 do PDest[i] := PSrc[20 i, 3]; // 不連續的 index >
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#10 引用回覆 回覆 發表時間:2003-05-14 17:08:35 IP:61.70.xxx.xxx 未訂閱
呵呵!你說的是這個阿!那就更簡單了! 查了一下!你就會發現 VarArrayCreate 是 WinAPI 的包裝 所以囉!原因知道了嗎? 當單維度陣列,所有編譯器都視同一連續記憶體來實做,所以 Move 最快 而當二維以上的陣列,則會因編譯器不同而有不同實做方式,不過其記憶體空間都是連續的!並沒有你所說的不連續(因該是說你的用詞不恰當,所以我才誤會囉!) 一般來說,陣列的記憶體實做分為 1. row major 2. column mahor Wins32 系列屬於 2. 而 C & Pascal 則採用 1. 的規則     考慮如下陣列 A[X,Y],column major 陣列對應到記憶體時,是以 Y 優先放入,因此在記憶體內是 A[0,0],A[0,1],A[0,2],A[0,3]...A[1,0],A[1,1]..等等,而 row major 則是以 X 為優先,A[0,0],A[1,0],A[2,0],A[3,0]...A[0,1],A[1,1]..等等    Window 是以 Wins32 位為主介面系統,採用 column major 原則,C & Pascal 採用 row major 原則,所以當用 VarArrayCreate 創造出來的陣列是 column major 與 Delphi 創造的是不同的,因此在對應上要轉個90度,不過通常編譯器會幫你處理,所以用索引的方式會較慢!因為還包含了額外的處理程式碼(這是編譯器自動加入的),而用 PV := VarArrayLock(V); 則是傳回陣列的第一個元素位置,如此直接存取當然較快,只是你就必須自己處理(因編譯器差異所導致的)陣列對應,只是這種差異就無法使用 move 來搬移了,這是先天上的差異,除非機器設計原理改變,不然永遠是這樣,就如同汽車不會飛,除非有新發明,即使軟體在進步也是無法改變硬體的限制!    所以並沒有你所說的不連續,因為沒有人規定X,Y座標一定要由X 開始遞增啊!兩者都是連續的使用記憶體空間,只是開始的軸向不一樣而已! 那三維以上的呢?一樣!將三維其拆成兩個二維,然後套用 1. 或 2. 的原則! 其實會有這種問題發生,乃是因為知識的不足,才會產生,如果相關知識充足,這個問題根本不存在!在下不是在說各位用功不夠!!絕無貶低各位的意思!只是提醒大家要多看書學習! 提供幾本書,有談到這個主題的: 1. {William Stallings}, Computer Organization & Architecture DESIGNING FOR PERFORMANCE 2. {Robert W. Sebesta} , Concepts of Programming Languages 3. {Silberschatz , Galvin , GaGne} , Operating System Concepts 希望這樣能釐清你的觀念與疑慮 !
引言: Syntax 兄誤會我的意思了 < > > 為甚麼會這樣.. 我就不清楚了< > 發表人 - > 發表人 - syntax 於 2003/05/14 17:24:59 發表人 - syntax 於 2003/05/15 11:26:04
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#11 引用回覆 回覆 發表時間:2003-05-14 17:23:50 IP:61.70.xxx.xxx 未訂閱
還有一本書也不錯看 有談到 Wins32 與記憶體技術 全華 的 Window 核心剖析 ! 發表人 - syntax 於 2003/05/14 17:29:08 發表人 - syntax 於 2003/05/15 11:26:57
shaofu
高階會員


發表:5
回覆:136
積分:103
註冊:2003-01-07

發送簡訊給我
#12 引用回覆 回覆 發表時間:2003-05-14 17:44:56 IP:210.243.xxx.xxx 未訂閱
這個.. row major 與 column major 我也是有點概念啦 < > ( 感謝 > 我想表達是這個, 有錯請指正 < > 發表人 -
shaofu
高階會員


發表:5
回覆:136
積分:103
註冊:2003-01-07

發送簡訊給我
#13 引用回覆 回覆 發表時間:2003-05-14 17:53:18 IP:210.243.xxx.xxx 未訂閱
另外"不連續"這個字很容易讓大家誤會, 在此更正! Lock 的那塊 Memory 當然是一整塊連續的 Memory (Lock 的目的), 只是因為 Memory Mapping (row major, column major) 的方式不同, 造成我認為"不連續"的現象! 我還是該多翻書了 @@ 發表人 - shaofu 於 2003/05/14 17:59:29
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#14 引用回覆 回覆 發表時間:2003-05-15 11:36:17 IP:61.70.xxx.xxx 未訂閱
補充一下 Lock 呼叫的是 SafeArrayAccessData  目的是: 是用來將 LockCount 值加 1 並傳回 第一筆資料的位址 不是用來鎖定該陣列  LockCount 是給作業系統運作所需之 細節可以參考 Wins32 SafeArray相關函式說明
引言: 另外"不連續"這個字很容易讓大家誤會, 在此更正! Lock 的那塊 Memory 當然是一整塊連續的 Memory (Lock 的目的), 只是因為 Memory Mapping (row major, column major) 的方式不同, 造成我認為"不連續"的現象! 我還是該多翻書了 @@ 發表人 - shaofu 於 2003/05/14 17:59:29
系統時間:2024-05-17 7:05:42
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!