一、提高Halcon的運算速度,有以下幾種方法:
1、Multithreading(多線程)
2、Automatic Parallelization(自動操作並行化)
3、Compute devices,利用GPU提速,如果顯卡性能好,至少可以提高5~10倍的運算速度
二、多線程
1、官方自帶的例程get_operator_info.hdev,可以查看支持多線程的算子;
1 * Determine the multithreading information 2 get_multithreading_operators (TypeExclusive, TypeMutual, TypeReentrant, TypeIndependent) 3 * 自定義函數展開之后,有get_operator_info算子 4 * get names of all operators of the library 5 get_operator_name ('', OperatorNames) 6 get_operator_info (OperatorNames[Index], 'parallelization', Information)
2、官方的手冊
C:\Program Files\MVTec\HALCON-19.11-Progress\doc\pdf\manuals\programmers_guide.pdf
Chapter 2 Parallel Programming and HALCON
C:\Program Files\MVTec\HALCON-19.11-Progress\doc\pdf\reference\reference_hdevelop.pdf
Chapter 25 System --- 25.6 Multithreading
三、多核並行
看看官方的說明,關於HALCON-多核性能:
1、算子自動並行化(AOP)
Automatic Operator Parallelization (AOP)
多核和多處理器的計算機顯著提升了計算機視覺系統的速度。八年多以來,HALCON提供了通過工業驗證的算子並行化,能很好地支持這種速度的提升。當然,並不是全部的視覺操作都能受益於並行化這種方式。因此,HALCON的智能算法可以確定是否需要用並行化方式——會考慮到具體的算法,算法的輸入值和硬件條件。
1 來自官方例程query_system_parameters.hdev 2 * Parallelization 3 get_system ('processor_num', ProcessorNum) 4 get_system ('thread_pool', ThreadPool) 5 get_system ('thread_num', ThreadNum) 6 *Automatic Operator Parallelization,默認值是true 7 get_system ('parallelize_operators', AOP) 8 *這個修飾符用於把函數定義為可重入函數,默認值是true;所謂可重入函數就是允許被遞歸調用的函數 9 get_system ('reentrant', Reentrant) 10 *故意關掉測試性能 11 *set_system('parallelize_operators','false')
並行HALCON在多核計算機上會自動將數據,比如圖像數據分配給多個線程,每一個線程對應一個內核。用戶甚至不需要改動已有的HALCON程序來就能使用自動划分功能,從而立即獲得顯著的速度提升。
2、並行編程
HALCON支持並行編程,如多線程的程序。它不僅僅是線程安全的而且可多次調用。因此多個線程可在同一時刻同時調用HALCON算子。利用這種特性,用戶可以將一個機器視覺應用軟件分解成多個獨立的部分,讓它們在不同的處理器上並行運行。
在一個四核的計算機上運行算子,HALCON會自動將圖像分為四部分,由四個線程並行處理。
在一個包含兩個Quad-Core Intel Xeon E5345,2.33 GHz在內的計算機上使用median_image算子(13×13的模板)對1280×1024的圖像進行濾波操作時,根據使用CPU核的數量的不同,加速因子分別為*1/1.96/2.90/3.79/4.51/5.48/6.34/6.93。注意:可以達到的最高加速因子與所用的HALCON算子和圖像大小有關。
3、AOP默認是激活的
(1)Halcon一方面提供自動操作員並行化(AOP)和手動並行化的手段。另一方面,對應用程序部分進行編程。自動操作員並行化(AOP)將輸入數據(例如圖像)分割成多個部分並進行處理數據部分獨立且並行。這也稱為數據並行化。
默認情況下,AOP是激活的,即這種類型的並行化是自動完成的,在許多情況下您不會至少對於單個操作員而言,必須關心進一步的數據並行化。有關AOP的詳細信息,請參見programmers_guide.pdf,第2.1節。
(2)Halcon還提供了optimize_aop算子,用於優化aop,提高性能。
默認情況下(即不使用optimize_aop算子),Halcon使用AOP的最大可用線程數,最多使用處理器數量。但是,根據傳遞給運算符的數據大小和參數集,最大線程數上的並行化可能會過度且效率低下。 optimize_aop根據線程號優化AOP,並針對HALCON運算符的並行處理檢查給定的硬件。這樣,它將檢查每個運算符,可以通過在tuple元組,channel通道或domain level域級別(不考慮the partial level部分級別)上的自動並行化來加快操作速度。每個檢查的運算符都將執行幾次(依次和並行),並帶有一組不斷變化的輸入參數值/圖像。后者有助於評估操作員的輸入參數特征(例如,輸入圖像的大小)與其並行處理效率之間的依賴性。根據操作員參數的設置,這可能要花費幾個小時。對於正確的優化,至關重要的是不要在計算機上同時運行任何其他計算密集型應用程序,因為這會嚴重影響硬件檢查的時間測量,從而導致錯誤的結果。
詳情參見官方例程optimize_aop.hdev
4、查看支持AOP的算子
自動並行化方法,為了實現運算符的自動並行化,HALCON利用數據並行性,即操作員的輸入數據可以彼此獨立地進行處理。數據並行性可以在四個位置找到。官方自帶的例程get_operator_info.hdev,可以查看;
(1)tuple level (2)channel level (3)domain level (4)internal data level
1 * Determine the parallelization method of all parallelized operators 2 get_parallel_method_operators (SplitTuple, SplitChannel, SplitDomain, SplitPartial, None) 3 AutoParallel := [SplitTuple,SplitChannel,SplitDomain,SplitPartial] 4 AutoParallel := uniq(sort(AutoParallel)) 5 * 自定義函數展開之后,有get_operator_info算子 6 * get names of all operators of the library 7 get_operator_name ('', OperatorNames) 8 get_operator_info (OperatorNames[Index], 'parallel_method', Information)
5、如果程序員不想使用AOP,而是自己實現並行化,那較為復雜,需要使用多線程技術,把圖像進行拆分處理,最后再合並。因此需要更多專業知識,詳情參見官方例程simulate_aop.hdev和官方說明書parallel_programming.pdf。
*set_system('parallelize_operators','false')
6、官方的手冊
C:\Program Files\MVTec\HALCON-19.11-Progress\doc\pdf\manuals\programmers_guide.pdf
Chapter 2 Parallel Programming and HALCON
C:\Program Files\MVTec\HALCON-19.11-Progress\doc\pdf\reference\reference_hdevelop.pdf
Chapter 25 System --- 25.8 Parallelization
C:\Program Files\MVTec\HALCON-19.11-Progress\doc\pdf\manuals\parallel_programming.pdf
四、GPU
1、Halcon中使用GPU提速,效果明顯。
Windows開始菜單--運行--輸入dxdiag--顯示,可以看到自己電腦的顯卡型號。
官方自帶的例程compute_devices.hdev,實現提速的優良效果,必須先關閉設備:dev_update_off();
1 來自官方例程compute_devices.hdev 2 * This example shows how to use compute devices with HALCON. 3 *
4 dev_update_off () 5 dev_close_window () 6 dev_open_window_fit_size (0, 0, 640, 480, -1, -1, WindowHandle) 7 set_display_font (WindowHandle, 16, 'mono', 'true', 'false') 8 *
9 * Get list of all available compute devices. 10 query_available_compute_devices (DeviceIdentifier) 11 *
12 * End example if no device could be found. 13 if (|DeviceIdentifier| == 0) 14 return () 15 endif 16 *
17 * Display basic information on detected devices. 18 disp_message (WindowHandle, 'Found ' + |DeviceIdentifier| + ' Compute Device(s):', 'window', 12, 12, 'black', 'true') 19 for Index := 0 to |DeviceIdentifier| - 1 by 1
20 get_compute_device_info (DeviceIdentifier[Index], 'name', DeviceName) 21 get_compute_device_info (DeviceIdentifier[Index], 'vendor', DeviceVendor) 22 Message[Index] := 'Device #' + Index + ': ' + DeviceVendor + ' ' + DeviceName 23 endfor 24 disp_message (WindowHandle, Message, 'window', 42, 12, 'white', 'false') 25 disp_continue_message (WindowHandle, 'black', 'true') 26 stop ()
2、操作GPU設備有關的算子:
query_available_compute_devices
get_compute_device_info
open_compute_device
init_compute_device
activate_compute_device
deactivate_compute_device
3、官方自帶的例程get_operator_info.hdev,可以查看支持GPU加速(OpenCL)的算子;
1 * Determine all operators that support OpenCL 2 get_opencl_operators (OpenCLSupport) 3 * 自定義函數展開之后,有get_operator_info算子 4 get_operator_name ('', OperatorNames) 5 get_operator_info (OperatorNames[Index], 'compute_device', Information)
這里舉例Halcon 19.11版本可以加速的算子有82個:
['abs_diff_image', 'abs_image', 'acos_image', 'add_image', 'affine_trans_image', 'affine_trans_image_size', 'area_center_gray', 'asin_image', 'atan2_image', 'atan_image', 'binocular_disparity_ms', 'binocular_distance_ms', 'binomial_filter', 'cfa_to_rgb', 'change_radial_distortion_image', 'convert_image_type', 'convol_image', 'cos_image', 'crop_domain', 'crop_part', 'crop_rectangle1', 'depth_from_focus', 'derivate_gauss', 'deviation_image', 'div_image', 'edges_image', 'edges_sub_pix', 'exp_image', 'find_ncc_model', 'find_ncc_models', 'gamma_image', 'gauss_filter', 'gauss_image', 'gray_closing_rect', 'gray_closing_shape', 'gray_dilation_rect', 'gray_dilation_shape', 'gray_erosion_rect', 'gray_erosion_shape', 'gray_histo', 'gray_opening_rect', 'gray_opening_shape', 'gray_projections', 'gray_range_rect', 'highpass_image', 'image_to_world_plane', 'invert_image', 'linear_trans_color', 'lines_gauss', 'log_image', 'lut_trans', 'map_image', 'max_image', 'mean_image', 'median_image', 'median_rect', 'min_image', 'mirror_image', 'mult_image', 'points_harris', 'polar_trans_image', 'polar_trans_image_ext', 'polar_trans_image_inv', 'pow_image', 'principal_comp', 'projective_trans_image', 'projective_trans_image_size', 'rgb1_to_gray', 'rgb3_to_gray', 'rotate_image', 'scale_image', 'sin_image', 'sobel_amp', 'sobel_dir', 'sqrt_image', 'sub_image', 'tan_image', 'texture_laws', 'trans_from_rgb', 'trans_to_rgb', 'zoom_image_factor', 'zoom_image_size']
4、官方手冊
C:\Program Files\MVTec\HALCON-19.11-Progress\doc\pdf\reference\reference_hdevelop.pdf
Chapter 25 System --- 25.1 Compute Devices
五、舉例測試
1 *參考官方例程optimize_aop.hdev;query_aop_info.hdev;simulate_aop.hdev; 2 *舉例edges_sub_pix算子性能測試 3 dev_update_off ()//實現提速的優良效果,必須先關閉設備
4 dev_close_window () 5 dev_open_window_fit_size (0, 0, 640, 480, -1, -1, WindowHandle) 6 set_display_font (WindowHandle, 16, 'mono', 'true', 'false') 7 get_system ('processor_num', NumCPUs) 8 get_system ('parallelize_operators', AOP) 9
10 *讀取圖片 11 read_image(Image, 'D:/hellowprld/2/1-.jpg') 12 *彩色轉灰度圖 13 count_channels (Image, Channels) 14 if (Channels == 3 or Channels == 4) 15 rgb1_to_gray (Image, ImageGray) 16 endif 17
18 alpha:=5
19 low:=10
20 high:=20
21
22 *測試1:去掉AOP,即沒有加速並行處理 23 set_system ('parallelize_operators', 'false') 24 get_system ('parallelize_operators', AOP) 25 count_seconds(T0) 26 edges_sub_pix (ImageGray, Edges1, 'canny', alpha, low, high) 27 count_seconds(T1) 28 Time0:=(T1-T0)*1000
29 stop() 30
31 *測試2:AOP自動加速並行處理 32 *Halcon的默認值是開啟AOP的,即parallelize_operators值為true 33 set_system ('parallelize_operators', 'true') 34 count_seconds(T1) 35 edges_sub_pix (ImageGray, Edges1, 'canny', alpha, low, high) 36 count_seconds(T2) 37 Time1:=(T2-T1)*1000
38 stop() 39
40 *測試3:GPU加速,支持GPU加速的算子Halcon19.11有82個 41 *GPU加速是先從CPU中將數據拷貝到GPU上處理,處理完成后再將數據從GPU拷貝到CPU上。從CPU到GPU再從GPU到CPU是要花費時間的。 42 *GPU加速一定會比正常的AOP運算速度快嗎?不一定!結果取決於顯卡的好壞. 43 query_available_compute_devices(DeviceIdentifiers) 44 DeviceHandle:=0
45 for i:=0 to |DeviceIdentifiers|-1 by 1
46 get_compute_device_info(DeviceIdentifiers[i], 'name', Nmae) 47 if (Nmae == 'GeForce GT 630')//根據GPU名稱打開GPU
48 open_compute_device(DeviceIdentifiers[i], DeviceHandle) 49 break
50 endif 51 endfor 52
53 if(DeviceHandle#0) 54 set_compute_device_param (DeviceHandle, 'asynchronous_execution', 'false') 55 init_compute_device(DeviceHandle, 'edges_sub_pix') 56 activate_compute_device(DeviceHandle) 57 endif 58
59 *獲得顯卡的信息 60 get_compute_device_param (DeviceHandle, 'buffer_cache_capacity', GenParamValue0)//默認值是顯卡緩存的1/3
61 get_compute_device_param (DeviceHandle, 'buffer_cache_used', GenParamValue1) 62 get_compute_device_param (DeviceHandle, 'image_cache_capacity', GenParamValue2) 63 get_compute_device_param (DeviceHandle, 'image_cache_used', GenParamValue3) 64
65 *GenParamValue0 := GenParamValue0 / 3
66 *set_compute_device_param (DeviceHandle, 'buffer_cache_capacity', GenParamValue0) 67 *get_compute_device_param (DeviceHandle, 'buffer_cache_capacity', GenParamValue4) 68
69 count_seconds(T3) 70 *如果顯卡緩存不夠,會報錯,error #4104 : Out of compute device memory 71 edges_sub_pix (ImageGray, Edges1, 'canny', alpha, low, high) 72 count_seconds(T4) 73 Time2:=(T4-T3)*1000
74
75 if(DeviceHandle#0) 76 deactivate_compute_device(DeviceHandle) 77 endif 78 stop() 79
80 *測試4:AOP手動優化 81 set_system ('parallelize_operators', 'true') 82 get_system ('parallelize_operators', AOP) 83
84 *4.1-優化線程數目方法'threshold'
85 optimize_aop ('edges_sub_pix', 'byte', 'no_file', ['file_mode','model','parameters'], ['nil','threshold','false']) 86
87 count_seconds(T5) 88 edges_sub_pix (ImageGray, Edges1, 'canny', alpha, low, high) 89 count_seconds(T6) 90 Time3:=(T6-T5)*1000
91
92 *4.2-優化線程數目方法'linear'
93 optimize_aop ('edges_sub_pix', 'byte', 'no_file', ['file_mode','model','parameters'], ['nil','linear','false']) 94
95 count_seconds(T7) 96 edges_sub_pix (ImageGray, Edges1, 'canny', alpha, low, high) 97 count_seconds(T8) 98 Time4:=(T8-T7)*1000
99 stop() 100
101 *4.3-優化線程數目方法'mlp'
102 optimize_aop ('edges_sub_pix', 'byte', 'no_file', ['file_mode','model','parameters'], ['nil','mlp','false']) 103
104 count_seconds(T9) 105 edges_sub_pix (ImageGray, Edges1, 'canny', alpha, low, high) 106 count_seconds(T10) 107 Time5:=(T10-T9)*1000
108 stop() 109
110 dev_clear_window() 111 Message := 'edges_sub_pix runtimes:'
112 Message[1] := 'CPU only Time0 without AOP='+Time0+'ms,'
113 Message[2] := 'CPU only Time1 with AOP='+Time1+'ms,'
114 Message[3] := 'GPU use Time2='+Time2+'ms,'
115 Message[4] := 'optimize Time3 threshold='+Time3+'ms'
116 Message[5] := 'optimize Time4 linear='+Time4+'ms'
117 Message[6] := 'optimize Time5 mlp='+Time5+'ms'
118 disp_message (WindowHandle, Message, 'window', 12, 12, 'red', 'false') 119 stop()
edges_sub_pix算子性能測試結果:
rotate_image算子性能測試結果:
得出的結論是:
1、GPU加速是先從CPU中將數據拷貝到GPU上處理,處理完成后再將數據從GPU拷貝到CPU上。從CPU到GPU再從GPU到CPU是要花費時間的。
2、GPU加速一定會比正常的AOP運算速度快嗎?不一定!結果取決於顯卡的好壞.
3、GPU加速,如果顯卡緩存不夠,會報錯,error #4104 : Out of compute device memory