四、 GMM 演算法實驗結果
4.2 GMM 去浮點數化之處理速度分析
因為不同的資料型態在 PC 上處理會有不同的處理速度,我們以一個乘法運 算的程式,計算以 Double、Float 及去浮點數化的三種格式作乘法運算所需要的 時間。以 Double 格式為例,如圖 4-1 所示,計算處理所需的時間,然後將其中 乘法運算的資料格式更換成其他去浮點數化資料格式,並加入包含去浮點數化所 需的資料位移步驟,以及將資料搬移至暫存的緩衝記憶體的過程來做測試,如圖 4-2 所示。
圖 4-1 乘法運算的基本測試迴圈程式碼
count = 5000;
for(i = 0;i<count;i++) {
for(j=0;j < count;j++) {
a_double = b_double*c_double;
} }
35
圖 4-2 各種資料型的乘法運算基本測試態運算程式碼
經過基本的乘法運算試測後,我們得到了上述各種資料格式乘法運算的執行 時間,如表格 4-5。然後以 Double 的格式乘法運算的執行時間為基底,計算與 各種資料格式乘法運算的執行時間的比例,這樣可得到 Float 格式以及各種去浮 點數化格式相對於 Double 格式的相對時間。再將時間取倒數,即得到了對 Double 格式乘法運算的相對速度。我們發現 Full 32-bit 格式(0.352)的速度最慢,因為計 算時須先將資料暫存到 64 位元的緩衝記憶體,除了搬移資料的動作外,使用 64 位元的緩衝記憶體也導致速度下降。Partial 32-bit 格式(0.998)的速度與 Double 格 式(1.0)的速度相近,因為他在計算完結果後需要再增加一個位移的動作,否則理 論上的整數格式的處理速度應該會比 Double 的格式較快。而 16-bit 格式(0.694) 的速度,並沒有想像中的更快,因為計算的過程中增加了將資料搬移至 32 位元 緩衝記憶體的動作,以及將最後計算結果位移的動作。
Double:
a_double = b_double*c_double;
Float:
a_float = b_float*c_float;
Full 32-bit:
a_long = b_int32;
a_long = c_int32;
a_long = b_long*c_long;
b_int32 = a_long >> 16;
Partial32-bit
a_int32 = b_int16*c_int16;
b_int16 = a_int32>>8;
16-bit
b_int32 = b_short c_int32 = c_short
a_int32 = b_int32 * c_int32;
a_short = a_int32>>8;
36
將 GMM 程式的視訊處理的測試時間,如表格 4-6 所示,與基本乘法的測試 結果做比對,如表格 4-7 所示。除了 16-bit 格式結果差距較大外,其餘的格式接 與基本乘法的測試結果相近,其主要原因為在 16-bit 格式的運算過程中,使用了 許多標準的 32 位元暫存的緩衝記憶體,除了最後的計算結果外,運算的過程中 並不需要每次再做資料搬移到 32 位元緩衝記憶體的動作,因此節省了許多將資 料搬移至暫存的緩衝記憶體的時間。
表格 4-5 以基本乘法計算測試之速度表
Data Type Double Float Full 32-bit Partial 32-bit 16-bit Time (ms) 56.064 56.144 159.179 56.180 80.763
Normal 1.000 1.001 2.839 1.002 1.441 Speed 1.000 0.999 0.352 0.998 0.694
表格 4-6 Test Video 以 GMM 程式作前景分析之處理速度表
Data Type Double Float Full 32-bit Partial 32-bit 16-bit TestVideo1 25.952 28.187 9.295 25.133 25.421 TestVideo2 25.757 28.185 8.835 24.179 24.980 TestVideo3 26.177 28.187 9.495 25.533 25.921 TestVideo4 25.585 28.807 9.095 23.956 24.676
單位: fps 表格 4-7 Test Video 以 GMM 程式作前景分析之速度比較表
Data Type Double Float Full 32-bit Partial 32-bit 16-bit TestVideo1 1.000 1.086 0.358 0.968 0.980 TestVideo2 1.000 1.094 0.343 0.939 0.970 TestVideo3 1.000 1.077 0.363 0.975 0.990 TestVideo4 1.000 1.126 0.355 0.936 0.964
37
除了利用乘法運算的測試方法,我們更進一步分析了在去浮點數化的資料格 式之 GMM 演算法程式中的指令複雜度,程式碼如圖 4-3~圖 4-6 所以,最後將其 匯整至表格 4-8。從指令複雜度計算的結果,可以看出使用去浮點數化的格式程 式碼之指令複雜度,明顯都比使用 Double 格式、Float 格式之程式碼的指令複雜 度高出許多。所以雖然在理論上,使用整數運算的處理速度應該會比使用浮點數 格式運算的處理速度快很多,但是卻無法明顯反應在去浮點數化後的 GMM 程式 之影像處理的輸出結果。不過至少在 Partial 32-bit 格式及 16-bit 格式,雖然其指 令複雜度高出 Double 格式許多,但是因為未使用到 64 位元的緩衝記憶體,所以 其處理速度可以維持接近 Double 格式的速度。
表格 4-8 GMM 涵式複雜度之分析表
Data Type Double Float Full 32-bit Partial 32-bit 16-bit Check matched Gaussian 83 83 155 137 146 Update foreground 14 14 14 14 14 Update Gaussian 70 70 124 106 113 Update background 21 21 24 24 24
Sum 188 188 317 281 297
單位:Statement
38
(a)
(b)
圖 4-3 Check matched Gaussian 函式的複雜度分析(a)Double and Float cases. (b)Full 32-bit case. (c)Partial 32-bit case. (d)16-bit case.
Double, Float case :
Full 32-bit case:
#define MEAN_SHIFT_BITS 24
#define MEAN_2_VAR_BITS 8
#define VAR_SHIFT_BITS 16
1. It, x = It, x << MEAN_SHIFT_BITS
39
(c)
(d)
圖 4-3 (續) Partial 32-bit case:
#define MEAN_SHIFT_BITS 8
#define MEAN_2_VAR_BITS 0
#define VAR_SHIFT_BITS 8
1. It, x = It, x << MEAN_SHIFT_BITS
#define MEAN_SHIFT_BITS 8
#define MEAN_2_VAR_BITS 0
#define VAR_SHIFT_BITS 8
1. It, x = It, x << MEAN_SHIFT_BITS
40
(a)
(b)
(c)
(d)
圖 4-4 Get weight learning rate 函式的指令複雜度分析(a)Double and Float cases. (b)Full 32-bit case. (c)Partial 32-bit case. (d)16-bit case.
Double, Float case :
#define WEIGHT_SHIFT_BITS 15 1. temp _132bit = (1 –βb)
Full 32-bit case:
#define WEIGHT_SHIFT_BITS 15 1. temp _164 bit = (1 –βb)
Partial 32-bit case:
#define WEIGHT_SHIFT_BITS 15 1. temp _132bit = (1 –βb)
2. temp _132 bit = temp _132 bit ×ηt-1,x (β) 3. temp _132bit = temp _132bit + ηb β b
4. ηt,x = temp _132bit >> WEIGHT_SHIFT_BITS Difference : (4– 3) = 1
41
(a)
圖 4-5 Update Gaussian 函式的指令複雜度分析(a)Double and Float cases. (b)Full 32-bit case.
(c)Partial 32-bit case. (d)16-bit case.
Double, Float case :
1. temp _1double = (1- ηt, x,(β)) //ηt, x(β) statements = 3 2. Wt,x, n = temp _1double × Wt-1,x, n
1. If Gaussian matched 2. temp _1double = (1- ρ) 3. temp _1double = tem 1. temp _1double × μt-1 x, n 2. temp _2double = ρ × It, x
3. μt, x, n = temp _1double + temp _2double 4. temp _1double = (1- ρ)
5. temp _1double = temp _1double × Vart-1 x, n 6. temp _2double = ρ × Varn
7. Vart, x, n = temp _1double + temp _2double 8. Wt,x, n = Wt,x, n +ηt, x(β)
9. else
10. μt, x, n = It, x 11. Vart, x, n = Var0 12. Wt,x, n = W0
1. Weightsum = ΣW //Sum weight
1. Wt,x, n = Wt,x, n / Weightsum //Normal weight Sum = 12+1+1 = 14
42
(b)
圖 4-5 (續) Full 32-bit case:
1. temp _164 bit = (1- ηt, x(β)) //ηt, x(β): statements = 5 2. temp _264 bit = Wt-1,x, n
3. temp _164 bit = temp _164 bit × temp _264 bit
4. Wt,x, n = temp _164 bit >> WEIGHT_SHIFT_BITS
1. If Gaussian matched 2. temp _164 bit = (1- ρ)
43
(c)
圖 4-5 (續) Partial 32-bit case:
1. temp _132 bit = (1- ηt, x(β)) //ηt, x(β) statements = 4 2. temp _132 bit = temp _132 bit × Wt-1,x, n
3. Wt,x, n = temp _132 bit >> WEIGHT_SHIFT_BITS
1. If Gaussian matched 2. temp _132 bit = (1- ρ)
Difference : ((7-5)+(2-1))× (Gaussian number)+ (20-11) × (Channels)
= 3 × 3 + 9 × 3 = 36
44
1. If Gaussian matched 2. temp _132 bit = (1- ρ)
45
(a)
(b)
(c)
(d)
圖 4-6 Update background 函式的指令複雜度分析(a)Double and Float cases. (b)Full 32-bit case.
(c)Partial 32-bit case. (d)16-bit case.
Double, Float case :
1. Bg_Data = μmax weight Sum = 1
16-bit case:
1. Bg_Data = μmax weight
2. Bg_Data = Bg_Data >> MEAN_SHIFT_BITS Difference : (2 – 1) × (Channels) = 3
Full 32-bit case:
1. Bg_Data = μmax weight
2. Bg_Data = Bg_Data >> MEAN_SHIFT_BITS Difference : (2 – 1) × (Channels) = 3
Partial 32-bit case:
1. Bg_Data = μmax weight
2. Bg_Data = Bg_Data >> MEAN_SHIFT_BITS Difference : (2 – 1) × (Channels) = 3
46
#define IMAGE_CHANNELS 3
#define MAX_OBJ_NUM 4800
double GaussPointWeight[GAUSS_NUM][IMAGE_HEIGHT][IMAGE_WIDTH];
double GaussPointMean[GAUSS_NUM][IMAGE_HEIGHT][IMAGE_WIDTH][IMAGE_CHANNELS];
double GaussPointVar[GAUSS_NUM][IMAGE_HEIGHT][IMAGE_WIDTH][IMAGE_CHANNELS];
double GaussPointEata[IMAGE_HEIGHT][IMAGE_WIDTH];
unsigned char GaussPointWeightLearningMode[IMAGE_HEIGHT][IMAGE_WIDTH];
unsigned int Match_Index[IMAGE_HEIGHT][IMAGE_WIDTH];
double Match_Var[IMAGE_HEIGHT][IMAGE_WIDTH][IMAGE_CHANNELS];
CC_Obj CC_Obj_buffer[2][MAX_OBJ_NUM];
CC_Obj *CC_Obj_Pre_Double;
CC_Obj *CC_Obj_Curr_Double;
unsigned int MaxObj_Curr_Double;
unsigned int MaxObj_Pre_Double;
unsigned int Obj_Num_Double;