2009年4月30日 星期四

一點關於 brook+ 的筆記...

這張圖是個人對 brook+ 的感想... -_-

1.記憶體要用 new ::brook::Stream 去產生 CAL 對應裝置 (不一定是 CPU or GPU) 裡的記憶體空間, 如宣告一個 vector, 一維陣列, 內容物是 float, 要 x 個大小:

unsigned int dim[1] = { x };
::brook::Stream<float> = new ::brook::Stream<float>(1, dim);

如果是二維, 假設是 x * y 大小的話:

unsigned int dim[2] = { x, y };
::brook::Stream<float> = new ::brook::Stream<float>(2, dim);

new 後面接的 1 跟 2 就是 dim 指標的最大深度, 也就是需要幾維, 後面會講到的 domain 也會用到這個概念.

##如果陣列內元素是 float4 或 int4 的話, 它一個元素就是 128bit 寬大小而非 32bit. 雖然這算常識但還是要提一下.
##我不確定最大可以到幾維, 好像是 4.

2."<>" 標記, 指的是一個值, 但是這個值是一個 vector 裡的一個元素, 而是哪一個則看它所屬的thread 是第幾個.

3.kernel function 內可以使用 instance() 取得現在是上述 vector 裡的第幾個元素, 如果是一維的話可以使用
int x=instance().x; 
取得座標點, 二維可以使用:
int2 p = instance().xy;
int x = p.x; //取出 x 座標的範例. 
int y = p.y; //取出 y 座標的範例.

因為 int 裡最大的就是 int4, 內值分別為 int4.x, int4.y, int4.z, int4.w 四個, 所以我猜記憶體最大可用維度應該是四維....

4.盡可能使用 <> 去跑, brook+ 裡會拆成好幾個 thread 去跑 (未證實. 據說這就是 scatter 機能..) 例如以下的 kernel function code:
kernel void copy(float input<>, out float output<>)
{
    output = input;
}
假設 input output 兩個 vector 長度都是 x 的話, 就會拆 x 個 thread 各別去做 data copy 的動作..

5.盡可能使用 <> 另一個理由是因為, array output 在目前的 brook+ 裡只能允許有一個.

6.brook+ 內每個 kernel function 不允許擁有自己的 local memory..

7.kernel function 內索引變數可以活用 int4 來做, 例如:

int4 nIDX = { 0, 0, 0, 0 };
int4 nSTP = { 1, 256, 1, 256 };

fOut = pfSrc[nIDX.x] + pfSrc[nIDX.y] + pfSrc[nIDX.z] + pfSrc[nIDX.w];
nIDX += nSTP;
......

int4 也可以改 float4, brook+ 內允許使用浮點數當索引值..

8.brook+ 內 kernel function 不允許呼叫其它的 kernel function..

9.output <> 的值無法拿來給 kernel function 程式做讀取之用, 要讀取再寫入 (a+=b 的場合) 的話要用 reduce 的寫法:
reduce void reduceGPU(float input<>, reduce float output<>)
{
    output += input;
}
但是 reduce 的限制很多, 只能有兩個參數, 就是這一進一出..
output [] 這種 array 型態的話就可以, 只是當你程式要讀取時, 通常該被更新的值都沒被更新.

10.kernel function 不可以做指標型態轉換, 也不支援 int <=> float 值的轉換.

11.外面要呼叫像第四個那種 copy function, 但只需要 copy 某一個範圍時, 可以下 domain 參數, 例如:
::brook::Stream<float> a[10];
::brook::Stream<float> b[10];
copy(a.domain(2, 6), b.domain(2, 6));
這樣就可以 copy a[2] ~ a[5] 給 b[2] ~ b[5].
附帶說明一點, 在這種寫法下, kernel function 內 instance().x 抓到的起始值是 0, 不會是 2.

brook+  一來它是 data parallel 而不像 nvcc 是 thread parallel 導向的做法, 而因為不管計算 float32 x1 或 float32 x4 (float4) ATi GPU 內部都是以 float32 x 4 在演算, 所以使用 float4 會比只用 float 有效率, 所以在這前提之下, 能夠把資料的平行化處理拆散到多少, 會關係效能以外, 甚至影響計算結果是否正確.

真是難寫死了... 特別是資料平行的演算法 -_-

2009年4月25日 星期六

Bluetooth 3.0

這一代就如同 pcadv 講的除了 BT 原本的協定以外再追加兩樣東西 1. 802.11 網路 (雖然 BT 原本就有自己的網路..), 一是 USB, 這個我有興趣很久了..
雖然看起來感覺像 802.11b/g/n 來跑 BT 3.0 的感覺...

2009年4月23日 星期四

HGST 7K250 爆震對抗記..

當一臺電腦的靜音改裝到某種程度時, 硬碟的噪音問題就會浮現上來, 而且特別是馬達產生的噪音和震動. 以下這兩顆 7K250 160G 服役四年餘間我也享受它的震動帶來的共震音四年 (所以以下都用爆震來形容, 別家的硬碟都沒它誇張), 直到最近才有接近完美的解法... -_-

原本買這機殼的動機就是因為它有硬碟專用的吸震墊, 用來對付有運轉爆震的兩顆 HGST 7K250 之用, 因為 7K250 馬達運轉中的劇烈震動會延著固定架傳到整個機殼, 再造成機殼共震, 整個機殼因為那兩顆硬碟搞的好像在演奏交響樂一樣... -_-

一開始, 裝上這個機殼後, 並不如有想像中的改善, seek 聲音是減少很多很多, 但馬達的爆震完全沒有減少的現像, 後來又再用聯力的 EX-33 改裝, 也不見有多少改善. 直到某天在玩 ace combat 6 玩到一半忽然想到, 可能就是因為架子太牢固, 才會把震波傳到整個機殼上, 於是我做個實驗, 把硬碟架整個移出機殼, 接線則和原本機殼內一樣的組態這要實驗看看, 果然有相當大的改善.

於是我就把機殼內的硬碟架整個改成這樣:

(左圖引自這裡) 左圖是改裝前的樣子, 底部會有一個架子固定整個硬碟架, 改裝就是把那個硬碟架拿掉, 上下塞入海棉等吸震材料夾起來.

改裝步驟裡最麻煩的, 就是拿掉那個硬碟架底座, 因為它有一個釘子铆在內側, 總共要拔掉三根釘子, 還有壓好的鋁帽, 如左圖示.
  
再來就是如右圖這樣, 因為架子已經沒了, 所以只能靠上下夾兩片吸震墊而且夾很緊, 來防止硬碟架的滑動.
如此一來, 我平常看文件寫 code 等 no loading 活動下終於可以耳根子清靜一點了.. -_-

2009年4月22日 星期三

[鬼扯] RAID5 可靠嗎?

其實羅貫中已經預言 RAID5 可不可靠了, 有圖有真像..



2009年4月21日 星期二

小試 icc11 後記..

以下的兩個設定很簡單, 就是把 SSE 選項全拿掉, 但 OpenMP 仍兩者都有.

vc9:
剩 /fp:fast, Enhance Instruction Set 為 No,
其它設定跟上篇一樣, 15531mS

icc11:
/QAXSSE? 與 /QXSSE? 全部取消, /Qfp-Speculationfast 不變, /fp:fast 不變.
15562mS
兩者差距幾乎可以視為是 OS 的干擾而已了...

跟之前 16 秒與 18 秒的差距, 老實講, 這是意料中的事情. 在這之前我把程式裡 feature filter 的部份用 assembly 下去寫 (因為這部份花掉時間佔 95% ), 結果是比 c code 還慢, 當時測試的結論是 SIMD code 如果執行時間很長 (執行超過 15mS 以上) 就會碰上 OS 做 content switch 時做 XMM register 備份, 會額外花掉很多時間在這上面, 而且即使是 x64 OS 下都不例外. 綜合之前跟別人討論 x86 SIMD coding 花的時間反而比一般 float 久的一個結論: "會說用 SSE 跑的會比較快, 沒寫過程式的人才會這樣說".

老實講, 不管是 AVX 還是 LNI, 多少抱持著看笑話的心態去看這些指令集.

還有一點補充就是, 這個程式不管是 train 還 detection 都是自己寫的, 不是 OpenCV 的 code 也不是用 IPP.

2009年4月20日 星期一

小試 icc 11..

首先寫在前面的, 安裝前請先注意, 環境變數中 path 裡的東西不可以有 () 出現.. (之前裝 DirectX SDK 手賤一直按 next 後的下場..)

測試程式有兩個, 一個是 paul viola 有篇 "Rapid Object Detection using a Boosted Cascade of Simple Features" (CVPR 2001) 講的 object detection 的 implement, 一個是這個 object detection 裡用的積分圖方法, 把這個積分圖方法獨立出來特別做測試.

icc 跟 vc9 相同 (或相近) 的參數:
/O3 (vc9 是 /ox)
/Ob2 (Any Suitable)
/Ot (Favor Fast Code)
/Oy (Omit Frame Pointers)

icc 的多了:
/Og (Global optimizations)
/Qipo (Interprocedural Optimization)
/GA (Optimizatize for Windows Appilication 不是 Galaxy Angel..)
/Qft-speculationfast (Floating=point speculation)
/QaxSSE2 (Intel Core and NetBrust uArch. w/SSE2)
  (AMD Barcelona 最多可以用到 /QaxSSE3, 不過這裡因為要跟 vc9 比較, 只用 SSE2.)
/QxSSE? 不能設定, 這個會先檢查是不是 intel 自家的 CPU 產品,
        不是的話 compile 會過但不給你跑... 嘿嘿...

/Qprof???? (Profile Guded Optimization) 這項要關掉, 否則會跑不完...

順路一提, 這兩個 VS project 裡都有 brook+ 的檔案, 照過.... :P

首先是第二個程式, 也就是積分圖的運算速度, 有沒有 SSE 的時間差別, 第一個是用一般浮點去計算, 第二個是用 SSE2 指令集下去算, 測試用的是 AMD Phenom 9500 (Agena, 其實就是 Barcelona) 2.2Ghz full-speed, 測試圖就是下面貼的那 ORL face 那張大圖片.

vc9:
bitch 1 fucking time 266.000000 mS
bitch 2 fucking time 78.000000 mS

icc11:
bitch 1 fucking time 178.000000 mS
bitch 2 fucking time 69.000000 mS

浮點有快蠻多的, SSE 就還好而已.

再來是第一支程式, Object detection 抓的是人臉, 測試圖是 ORL face database 把所有 400 人的人臉圖合成一張 4096 x 4096 大小的大圖:
跟第一個程式不一樣的是, 這個有 OpenMP 的支援, 運作途中四顆 CPU 都是 100% full loading.

vc9: 16.75秒
icc11: 18.078秒.

不過, 這隻程式我指標用的非常兇, 以下是這兩個 code 的簡短差別...
1. (SSE bitchmark)
{
        int             nT      =       0;
        int             nB      =       width;

        for(int y=height-1; y>0; --y, ++nT, ++nB)
        {
                for(int x=width-1; x>0; --x, ++nT, ++nB)
                {
                        buf[nB+1] += buf[nB] + buf[nT+1] - buf[nT];
                }
        }
}

2. (Adaboost Object etection)
{
        float   *pdS, *pdT, *pdU, *pdV, *pdW;
        
        pdT             =       buf + width + 1;   
        pdV             =       buf + width;            
        pdU             =       buf + 1;                        
        pdS             =       buf;                               
        pdW             =       pdV + width - 1;
        for(; pdT<zoe; pdT++, pdU++, pdS++, pdV++, pdW+=width)
        {
                for(; pdV<pdW; pdT++, pdU++, pdV++, pdS++)
                {
                        *pdT    +=      *pdU + *pdV - *pdS;
                }
        }






}

目前這隻程式的 optimization 冠軍仍舊是 gcc 3.4.6 cygwin 版...

近一個月 K brook+ 的 sample code 跟 tune 以前的 code 的感想是, 指標能不要用就不要用, 在新一點的 compiler 裡只會跑的更慢 -_-|||b (brook+ 裡直接不能使用指標..)

2009年4月13日 星期一

catalyst 9.4

只是更新版本就沒啥了, 有不一樣的是 9.4 版可以讓 stream 支援 on board VGA (760G, 780V, 780G, 790GX). 

有沒有那實際效益就再說, 手上沒 780G 的板子可以測, 也不確定有沒有 SidePort Memory 會不會有差別..

2009年4月8日 星期三