這是Bee的舊文章,貼出來讓大家參考。
這是Bee見過最好的文章,來解釋指標效能及寫法的影響。
取自"Pointer on C"由Kenneth A. Reek所著。
簡體書為"C和指針",人民郵電出版社出版。
內容的一段我簡單說明。
範例是使用68000處理器
程式碼共用此段宣告
#define SIZE 50
int x[SIZE];
int y[SIZE];
int i;
int *p1, *p2;
第一個程式
void try1()
{
for( i =0; i< SIZE; i++ )
x[i] = y[i];
}
很直覺的寫法。
組合語言碼為
_try1: clrl _i
jra L20
L20001: movl _i,d0
asll #2,d0
movl #_y,a0
movl _i,d1
asll #2,d1
movl #_x,a1
movl a0@(0,d0:L),a1@(0,d1:L)
addql #1,_i
L20: moveq #50,d0
cmpl _i,d0
jgt L20001
第二個程式
void try2()
{
for( p1 = x, p2 = y; p1 - x < SIZE; )
*p1++ = *p2++;
}
改使用指標。
組合語言碼為
_try2: movl #_x,_p1
movl #_y,_p2
jra L25
L20003: movl _p2,a0
movl _p1,a1
movl a0@,a1@
addql #4,_p2
addql #4,_p1
L25: moveq #4,d0
movl d0,sp@-
movl _p1,d0
subl #_x,d0
movl d0,sp@-
jbsr ldiv
addql #8,sp
moveq #50,d1
cmpl d0,d1
jgt L20003
組合語言碼變長了,而且因為指標相減調整(除4)而去呼叫ldiv函式。增加許多執行時間。
第三個程式
void try3()
{
for( i = 0, p1 = x, p2 = y; i < SIZE; i++ )
*p1++ = *p2++;
}
計數改用變數,不讓指標調整。
組合語言碼為
_try3: clrl _i
movl #_x,_p1
movl #_y,_p2
jra L30
L20005: movl _p2,a0
movl _p1,a1
movl a0@,a1@
addql #4,_p2
addql #4,_p1
addql #1,_i
L30: moveq #50,d0
cmpl _i,d0
jgt L20005
似乎不錯。但還有更好。
第四個程式
void try4()
{
register int *p1, *p2;
register int i;
for( i = 0, p1 = x, p 2= y; i < SIZE; i++ )
*p1++ = *p2++;
}
使用暫存器變數宣告,將區域變數使用暫存器。
組合語言碼為
_try4: moveq #0,d7
movl #_x,a5
movl #_y,a4
jra L35
L20007: movl a4@+,a5@+
addql #1,d7
L35: moveq #50,d0
cmpl d7,d0
jgt L20007
如果夠了解編譯器及語言特性,就會找到更好的調整。
第五個程式
void try5()
{
register int *p1, *p2;
for( p1 = x, p2 = y; p1 < &x[SIZE]; )
*p1++ = *p2++;
}
移除計數。
組合語言碼為
_try5: movl #_x,a5
movl #_y,a4
jra L40
L20009: movl a4@+,a5@+
L40: cmpl #_x+200,a5
jcs L20009
最精簡。但C原始碼可讀性極差。
這個例子可以看出效能及可讀性之間的移轉。
也可以看出如何依組合語言碼而調整C程式碼。
到底是要好讀,還是效能,端看使用場合而定。
2010年2月3日 星期三
C語言:浮點數通信傳輸
這是Bee的舊文章,只是每隔一兩年就會有人提。那就改貼在這裡吧!
這是Bee在做控制系統時發生的一種狀況:必須將浮點數經通信傳輸到遠端控制器上,如使用DSP做為控制器等裝置,或是網路應用等。
但通信裝置資料多半是使用串列通信的方式,如一次傳輸一個Btye的方式做傳輸,而浮點數至少是32位元的資料。
Bee用C語言資料結構解決了此問題,可是我在網路上DSP討論區也發現有人也有相同問題,只不過是用指標來解決。
我整理以此兩種方法的解決方式:
1.指標方法:
void put_float(float a)
{
char *cp=(char*)&a;
Output(*cp++);
Output(*cp++);
Output(*cp++);
Output(*cp);
}
float get_float()
{
float f;
char *c = (char*)&f;
c[0] = Input();
c[1] = Input();
c[2] = Input();
c[3] = Input();
return f;
}
使用指標鑄型將要用的float資料或char資料取出及存入。
2.資料結構方法:
void put_float(float a)
{
union {
float f;
char c[4];
}var;
var.f = a;
Output(var.c[0]);
Output(var.c[1]);
Output(var.c[2]);
Output(var.c[3]);
}
float get_float(void)
{
union {
float f;
char c[4];
}var;
var.c[0] = Input();
var.c[1] = Input();
var.c[2] = Input();
var.c[3] = Input();
return (var.f);
}
使用共用資料結構union,做資料交換的中間資料存放。
結論:
要注意浮點數存入記憶體的結構,在不同CPU上可能使用不同順序,一端為Big Endian資料格式的CPU,而另一端為Little Endian的CPU,則必須注意存放及取用順序的不同。
就結果論,兩種方法沒有好壞。但以維護性來說使用資料結構方式因可讀性高,會比較好。而我也建議使用此方法。
這是Bee在做控制系統時發生的一種狀況:必須將浮點數經通信傳輸到遠端控制器上,如使用DSP做為控制器等裝置,或是網路應用等。
但通信裝置資料多半是使用串列通信的方式,如一次傳輸一個Btye的方式做傳輸,而浮點數至少是32位元的資料。
Bee用C語言資料結構解決了此問題,可是我在網路上DSP討論區也發現有人也有相同問題,只不過是用指標來解決。
我整理以此兩種方法的解決方式:
1.指標方法:
void put_float(float a)
{
char *cp=(char*)&a;
Output(*cp++);
Output(*cp++);
Output(*cp++);
Output(*cp);
}
float get_float()
{
float f;
char *c = (char*)&f;
c[0] = Input();
c[1] = Input();
c[2] = Input();
c[3] = Input();
return f;
}
使用指標鑄型將要用的float資料或char資料取出及存入。
2.資料結構方法:
void put_float(float a)
{
union {
float f;
char c[4];
}var;
var.f = a;
Output(var.c[0]);
Output(var.c[1]);
Output(var.c[2]);
Output(var.c[3]);
}
float get_float(void)
{
union {
float f;
char c[4];
}var;
var.c[0] = Input();
var.c[1] = Input();
var.c[2] = Input();
var.c[3] = Input();
return (var.f);
}
使用共用資料結構union,做資料交換的中間資料存放。
結論:
要注意浮點數存入記憶體的結構,在不同CPU上可能使用不同順序,一端為Big Endian資料格式的CPU,而另一端為Little Endian的CPU,則必須注意存放及取用順序的不同。
就結果論,兩種方法沒有好壞。但以維護性來說使用資料結構方式因可讀性高,會比較好。而我也建議使用此方法。
2010年2月2日 星期二
GTX275基本測試資料
發現沒有放GTX275的測試資料,補一下。
PC配備:
CPU
AMD Phenom(tm) 9350e
Quad-Core Processor 2.00 GHz
O.S.
Windows XP SP3
RAM
DDR2-800 2G*4(但O.S.只有顯示使用3.25G)
測試圖:
不過GTX275現在買不太到了,可能也要絶版了。現在GTX260以上的卡都不好買。
也許是缺貨加上世代交替的影響。再來玩的CUDA都會換新卡了吧!
PC配備:
CPU
AMD Phenom(tm) 9350e
Quad-Core Processor 2.00 GHz
O.S.
Windows XP SP3
RAM
DDR2-800 2G*4(但O.S.只有顯示使用3.25G)
測試圖:
不過GTX275現在買不太到了,可能也要絶版了。現在GTX260以上的卡都不好買。
也許是缺貨加上世代交替的影響。再來玩的CUDA都會換新卡了吧!
2010年1月26日 星期二
視差值計算原理
Bee最近被問到視差值如何計算,還是貼圖舉例說明比較容易。
首先找二張有視差的圖:
相減圖片:
其實有人從相減的圖片中就已經在猜視差值。
在數學計算上面,要找出最像的地方。最簡單的就是做移位再相減取絕對值。
每移動一個點,就會產生一個值。
但因單點判定有可能誤判,所以通常是連同附近的圖一併做計算,將所有的差值和記錄下來。
如果圖片夠像,其差值和就會最小。所以找出最小值是移位多少pixel,其移位值就是視差值。
以下為x=71,y=106(Matlab座標)附近取出的sad值分布圖:
x軸為位移,y軸為和。
可以知道此處以15為最低的值。故視差即為15。
這只是計算一個點,其實是整個圖每一點都要算,所以運算量很大。
以下為Matlab程式:
close all;clear all;
l_img=imread('corridorL.bmp');
r_img=imread('corridorR.bmp');
figure;imshow(l_img);
figure;imshow(r_img);
l=double(l_img);
r=double(r_img);
d=l-r;
figure;imshow(uint8(abs(d)));
[hight,weight]=size(l_img);
range=8;
search=64;
x=71;
y=106;
m=1;
if( search > weight-2*range )
search = weight-2*range;
end
while(m <= search)
n=1;
sad(m)=0;
while( n <= 2*range+1)
sad(m)=sad(m)+abs(l(x+n,y)-r(x-m+n-1,y));
n=n+1;
end
m=m+1;
end
figure;plot(sad);
首先找二張有視差的圖:
相減圖片:
其實有人從相減的圖片中就已經在猜視差值。
在數學計算上面,要找出最像的地方。最簡單的就是做移位再相減取絕對值。
每移動一個點,就會產生一個值。
但因單點判定有可能誤判,所以通常是連同附近的圖一併做計算,將所有的差值和記錄下來。
如果圖片夠像,其差值和就會最小。所以找出最小值是移位多少pixel,其移位值就是視差值。
以下為x=71,y=106(Matlab座標)附近取出的sad值分布圖:
x軸為位移,y軸為和。
可以知道此處以15為最低的值。故視差即為15。
這只是計算一個點,其實是整個圖每一點都要算,所以運算量很大。
以下為Matlab程式:
close all;clear all;
l_img=imread('corridorL.bmp');
r_img=imread('corridorR.bmp');
figure;imshow(l_img);
figure;imshow(r_img);
l=double(l_img);
r=double(r_img);
d=l-r;
figure;imshow(uint8(abs(d)));
[hight,weight]=size(l_img);
range=8;
search=64;
x=71;
y=106;
m=1;
if( search > weight-2*range )
search = weight-2*range;
end
while(m <= search)
n=1;
sad(m)=0;
while( n <= 2*range+1)
sad(m)=sad(m)+abs(l(x+n,y)-r(x-m+n-1,y));
n=n+1;
end
m=m+1;
end
figure;plot(sad);
2010年1月25日 星期一
種瓜得豆?
最近在想,Bee做什麼都是半路出家。常常種瓜得豆,不知是心不專,還是命如此?
大學讀化學系,本想考的是電機,分數上不去,也只好讀。後來因為要考材料所,去電機系上工程數學的課程,結果讀了一個電機的雙學位。然後去考電機研究所,結果沒上,只好去當兵。
後來化學系的同學都在LCD面板業賺到了他們的第一桶金,而Bee還在寫組合語言努力中。
本想說大學學了自動控制,可以在控制上發揮,結果光是電腦語言就搞不定。
為了搞定電腦,自學編譯器原理及作業系統理論。這原本是資工系的大難題,Bee也花了數年才會。
後來發現FPGA興起,就為了去學而換公司。差不多用了二年半,因公司政治而中斷,回到了Bee原先的嵌入式系統去做維護工作。
維護對研發人員本就不是長期的飯票,所以改去讀書,想改走機器人研究。其實這是嵌入式系統的加強,又有機會整合FPGA。
讀書的學科有一半和影像處理相關,主要是考量機器人中就以影像最有發展。本來是想以FPGA解決機器人環境認知問題。
中途發現以GPGPU做影像處理比FPGA來得快,於是去參加比賽。
後來指導教授換校,我只能另找,找另一位有做機器人控制的教授。結果Bee現在人在機器人控制的影像組,搞起影像處理了。
種瓜得瓜,種豆得豆,在人生的道路上好像不是。還是我耕耘得不夠久就換,所以長不出原先種的?
真的要好好檢討了。
大學讀化學系,本想考的是電機,分數上不去,也只好讀。後來因為要考材料所,去電機系上工程數學的課程,結果讀了一個電機的雙學位。然後去考電機研究所,結果沒上,只好去當兵。
後來化學系的同學都在LCD面板業賺到了他們的第一桶金,而Bee還在寫組合語言努力中。
本想說大學學了自動控制,可以在控制上發揮,結果光是電腦語言就搞不定。
為了搞定電腦,自學編譯器原理及作業系統理論。這原本是資工系的大難題,Bee也花了數年才會。
後來發現FPGA興起,就為了去學而換公司。差不多用了二年半,因公司政治而中斷,回到了Bee原先的嵌入式系統去做維護工作。
維護對研發人員本就不是長期的飯票,所以改去讀書,想改走機器人研究。其實這是嵌入式系統的加強,又有機會整合FPGA。
讀書的學科有一半和影像處理相關,主要是考量機器人中就以影像最有發展。本來是想以FPGA解決機器人環境認知問題。
中途發現以GPGPU做影像處理比FPGA來得快,於是去參加比賽。
後來指導教授換校,我只能另找,找另一位有做機器人控制的教授。結果Bee現在人在機器人控制的影像組,搞起影像處理了。
種瓜得瓜,種豆得豆,在人生的道路上好像不是。還是我耕耘得不夠久就換,所以長不出原先種的?
真的要好好檢討了。
2010年1月21日 星期四
使用GPU-Z看GPU狀況
想知道GPU有多操,所以找來這個軟體看看。結果還很好玩。
主要畫面:
在玩Game時,還可以看到不同形態的Game具有不同影響。
也可以觀察溫度的狀況,來了解功耗。
其他檢測:
不過有些資訊也是有這個GPU-Z才得以解釋。
像是在CUDA中測效能時,必須利用GPU內部timer來測。但有一行程式一直無法理解,其註解寫著Warm up。
結果一看到GPU-Z去監視CUDA運行時的利用率,我馬上理解出了什麼事。
原來GPU沒事要進入省電狀況,主要是調整Clock的方式來做。
在玩Game時會動態調整clock及負載狀況。
而在使用CUDA模式時會直接跳到最高的clock。所以需要一段時間做Warm up。
GTX275測得資料:
GTX275感測器狀況:
可以發現多了幾個溫度感知。
GTX275執行CUDA時狀況:
GTX275玩Game時的狀況
沒想到Game沒有操到滿。
GTX275執行完CUDA後很快回復到省電模式。
追加在ION上測到的資料
主要畫面:
在玩Game時,還可以看到不同形態的Game具有不同影響。
也可以觀察溫度的狀況,來了解功耗。
其他檢測:
不過有些資訊也是有這個GPU-Z才得以解釋。
像是在CUDA中測效能時,必須利用GPU內部timer來測。但有一行程式一直無法理解,其註解寫著Warm up。
結果一看到GPU-Z去監視CUDA運行時的利用率,我馬上理解出了什麼事。
原來GPU沒事要進入省電狀況,主要是調整Clock的方式來做。
在玩Game時會動態調整clock及負載狀況。
而在使用CUDA模式時會直接跳到最高的clock。所以需要一段時間做Warm up。
GTX275測得資料:
GTX275感測器狀況:
可以發現多了幾個溫度感知。
GTX275執行CUDA時狀況:
GTX275玩Game時的狀況
沒想到Game沒有操到滿。
GTX275執行完CUDA後很快回復到省電模式。
追加在ION上測到的資料
2010年1月5日 星期二
顯示卡升級為GTX275
因應顯示卡瓦數及接頭,一併更換電源供應器,升級到550W。
Power Supply套件。
本次主角Galaxy GTX275。
顯示卡套件。
顯示卡本體,這個很大。之前看照片還沒有發覺。也有點重量。重點是Bee要雙風扇。
輸出界面。
有五支熱導管。
裝進機殼後。因為卡很大,還要用特定角度才進得去。這台電腦也升到頂了,記憶體也是滿的,最多換硬碟了。
Power Supply套件。
本次主角Galaxy GTX275。
顯示卡套件。
顯示卡本體,這個很大。之前看照片還沒有發覺。也有點重量。重點是Bee要雙風扇。
輸出界面。
有五支熱導管。
裝進機殼後。因為卡很大,還要用特定角度才進得去。這台電腦也升到頂了,記憶體也是滿的,最多換硬碟了。
訂閱:
意見 (Atom)






















