前幾天技術大牛Vczh同學開發了一個函數圖像繪制程序,可以畫出方程f(x,y)=0的圖像。他的原理是用圖像上每一點的坐標帶入函數f得到針對x和y的兩個方程,再用牛頓迭代法求解得到一組點集,然后畫到圖像上。用他的程序可以畫出各種各樣令人驚嘆的方程圖形。但是他的程序非常慢,因為對每一個點坐標都用牛頓迭代法求解是一項很費時的任務,即使采用了Parallel.For,CPU算起來也很吃力。我研究了他的程序之后覺得可以用擅長并行計算的顯卡來加速迭代法求解的過程。用OpenCL來完成這個任務再合適不過了。
?
整個過程還是相當順利的,完全在Vczh原始程序的基礎上改成。僅稍微改變了策略。步驟如下:
- 解析輸入函數f之后,分別生成?f/?x和?f/?y兩個偏導數,然后將這三個二元函數轉化為合法的OpenCL表達式。
- 用OpenCL實現牛頓迭代法。
- 將圖像上的每一點分派到一個OpenCL線程,然后由無數并行的OpenCL線程計算自己的點。
?
其中OpenCL代碼如下:
fp_t func(fp_t x, fp_t y) { return {動態生成}; }fp_t df_dx(fp_t x, fp_t y) {return {動態生成}; }fp_t df_dy(fp_t x, fp_t y) {return {動態生成}; }fp_t solvex(fp_t start, const fp_t consty) {for (int i = 0; i < MAX_ITER; ++i){fp_t result = func(start, consty);if (result <= EPSILON && result >= -EPSILON){return start;}fp_t d = df_dx(start, consty);if (d <= EPSILON && d >= -EPSILON){return NAN;}else{start -= result / d;}}return NAN; }kernel void ComputeX(global write_only fp_t* points,int unit,int width,int cx,int cy,float origin_x,float origin_y) {int gx = get_global_id(0);int gy = get_global_id(1);uint write_loc = gx + gy * width;fp_t py = origin_y + (fp_t)(gy + 1 - cy) / unit;fp_t px = origin_x + (fp_t)(cx - gx - 1) / unit;points[write_loc] = solvex(px, py); } |
這是求解f(x, a) = 0部分的代碼,求解f(b, y) = 0的與之基本一樣。其中fp_t是根據情況定義的typedef,可能是float或double。因為不是所有的OpenCL設備都支持雙精度浮點,所以要寫成通用類型的算法,用宏來控制。
?
在.NET中使用OpenCL,最容易的方法當然是使用Cloo庫。Coo庫完整地封裝了OpenCL(1.1)的所有函數,并且是.NET非常容易使用的對象模型。我只使用了一次Cloo和OpenCL就再也不想忍受DirectX ComputeShader那麻煩的要死的類庫。。
?
我的程序源代碼已經完全上傳到github。地址是:https://github.com/Ninputer/opencl-plot 點擊Download即可打包下載所有代碼。想直接運行的朋友可以點擊此處下載二進制文件包。
?
要想運行這個程序,你必須安裝了OpenCL的實現平臺。目前Windows上的OpenCL主要有NVidia、AMD和Intel幾家提供的實現平臺。如果你有一塊比較新的NVidia或AMD顯卡,那么只需要裝了最新的驅動包就自帶了OpenCL。以下顯卡支持雙精度浮點:NVidia GeForce 200系列、400系列、500系列顯卡;AMD Radeon HD 5800、5900、6900系列。其中Radeon 6900系列尚不支持官方雙精度浮點數(cl_khr_fp64)擴展,所以本程序也支持cl_amd_fp64雙精度浮點擴展,功能上完全一樣。G80和RV770等架構的顯卡以及AMD中低端顯卡只能支持單精度浮點數,繪制時的精度可能會略差。
?
沒有支持OpenCL顯卡的同學也可以用多核CPU來進行OpenCL計算,仍然要比原始的C#版本快一些。如果使用Intel Core i3、i5、i7系列CPU,可以使用Intel OpenCL SDK,下載地址:http://software.intel.com/en-us/articles/opencl-sdk/ 其他多核CPU都可以使用AMD APP SDK,下載地址:http://developer.amd.com/sdks/AMDAPPSDK/downloads/Pages/default.aspx
?
啟動程序后允許先選擇OpenCL計算平臺和設備,如果安裝了多個OpenCL平臺可以任意選擇。目前本程序暫時不支持多顯卡并聯技術(SLI、Crossfire)。NVidia CUDA平臺界面示例:
?
AMD APP平臺界面示例:
?
Intel OpenCL平臺界面示例:
?
現在,輸入方程,充分發揮你的想象力吧!
注意采用顯卡計算時,最好不要進行游戲,用IE9瀏覽網頁等,負荷過重時可能會導致GPU重置。如果某些公式運算量太大,或顯卡較為低端,也容易導致GPU重置,請務必用Windows 7和Vista來進行實驗,因為WDDM驅動模型更加穩定(用XP容易藍屏)。