OpenCL 是 Mac OS X 10.6 "Snow Leopard" 的新功能之一,也是第一個正式支援 OpenCL 的作業系統。這裡就簡單介紹一下,如何在 Snow Leopard 下使用 Xcode 建立一個 OpenCL 的程式。 首先,要特別注意的是,必須安裝針對 Snow Leopard 的最新版 Xcode Version 3.2 (1060)。在 Snow Leopard 的安裝光碟中,有一個 Optional Install 的目錄中,可以找到新版 Xcode 的安裝程式。如果你沒有安裝過 Xcode,那麼,在安裝完後,可以在硬碟根目錄的 Developer/Applications 目錄下找到 Xcode 和 Interface Builder 等程式。如果經常要使用的話,可以把它們拉到 dock 上面。 現在執行 Xcode。它可能會出現一個 "Welcome to Xcode" 的畫面,可以讓你選擇建立新的 project,或是從最近打開過的 project 中選擇一個。這裡我們選擇 "Create a new Xcode project" 來建立一個新的 project。如果你的 Xcode 沒有顯示這個畫面,也可以直接從選單的 File/New Project... 來建立一個新的 project。這時,它會顯示一個 "New Project" 視窗,有很多各種不同的 project 種類可以選擇。在這裡,為了簡單起見,我們只做一個 command line 模式的程式。因此,在 Mac OS X 的 Application 中,選擇 "Command Line Tool" 這個選項。在 Type 中選擇 "C" 語言,然後按下 "Choose..." 按鈕。 現在你要為你的 project 選一個儲存的位置以及一個適當的名字。找一個你喜歡的位置,並輸入 hello_cl (或是任何你喜歡的名字)為 project 的名字,然後按下 "Save"。 現在 Xcode 會幫你建好一個完整的 project,包括一些程式檔,例如 main.c。不過,在開始寫 OpenCL 程式之前,還需要做一些小調整。首先,在選單中選擇 Project/Edit Project Settings... 來修改一些 project 的設定。它會顯示出 Project "hello_cl" Info 的對話框。預設的設定中,只有一個需要修改,也就是我們希望它只編譯出 Intel 架構的執行檔(這是因為 Snow Leopard 並不支援 PowerPC 架構)。選擇 "Build" tab,並在 Configuration 中選擇 "All Configurations",然後在 "Valid Architectures" 上按兩下,它預設選擇的各種 Architecture 中,把所有 ppc 開頭的都移除,也就是只留下 "i386" 和 "x86_64" 這兩個選項。現在可以把這個對話框關閉。 接下來,我們要把 OpenCL Framework 加到 project 中。在左邊的 "Groups & Files" 中,最上面有 "hello_cl",在上面按下右鍵(如果你的滑鼠因為某些神秘的原因沒有右鍵,可以按 control+左鍵),然後選擇 Add->Existing Frameworks...。它會列出一大堆系統中的 framework 讓你選擇。往下拉找到 OpenCL.framework 並選擇它,按下 Add 按鈕,就會把 OpenCL.framework 加到 project 中。 在 Source 中選 main.c,會顯示出 Xcode 預先產生的簡單 "Hello, world!" 程式碼。把它的內容改成如下:
{ cl_context context; cl_device_id *devices; char *devname; size_t cb; // create a GPU context context = clCreateContextFromType(NULL, CL_DEVICE_TYPE_GPU, NULL, NULL, NULL); if(context == 0) { printf("Can't create GPU context\n"); return 0; } // get a list of devices clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &cb); devices = (cl_device_id*) malloc(cb); clGetContextInfo(context, CL_CONTEXT_DEVICES, cb, devices, 0); // show the name of the first device clGetDeviceInfo(devices[0], CL_DEVICE_NAME, 0, NULL, &cb); devname = (char*) malloc(cb); clGetDeviceInfo(devices[0], CL_DEVICE_NAME, cb, devname, 0); printf("Device: %s\n", devname); // release everything free(devname); free(devices); clReleaseContext(context); return 0; } 按下 "Build and Run" 圖示,Xcode 就會編譯並執行程式。一切順利的話,它應該會執行,並在左下角顯示出 "Debugging of "hello_cl" ended normally." 的訊息。要看到執行結果,可以選擇選單的 Run/Console 顯示 Debugger Console 的結果。正常的話,應該可以在 "Running..." 後面看到程式執行所印出的 "Device: XXX" 字串。 如果程式印出的是 "Can't create GPU context" 字串,那麼可能表示你的系統並沒有支援 OpenCL 的 GPU。可以把程式中,呼叫 clCreateContextFromType 函式的參數中,CL_DEVICE_TYPE_GPU 改成 CL_DEVICE_TYPE_CPU,表示建立 CPU device,或是改成 CL_DEVICE_TYPE_DEFAULT 表示選擇預設的 device。 接下來簡單介紹一下程式的內容。 首先,所有的 OpenCL 函式都是在 OpenCL/opencl.h 中宣告的。所以,所有的 OpenCL 程式都要 #include <OpenCL/opencl.h>。 接下來,是建立一個 OpenCL 的 context。OpenCL 的 context 是用來管理包括 command queue、memory object、program 等等各種物件。使用 clCreateContextFromType 函式,可以很簡便的指定一個 device 的類型,就能建立一個 context。為了簡單起見,這裡就不再說明其它的參數是什麼意思了,有興趣的人可以自行參考 OpenCL Specification,或是相關的文件。這裡我們只指定第二個參數,也就是 device 的類型。它可以是下列各種的其中一種:
clCreateContextFromType 會傳回建好的 OpenCL context。如果 clCreateContextFromType 失敗,則會傳回 0。 一個 OpenCL context 裡面可能包括多個 device(例如一部電腦中可能有多個顯示晶片),所以我們要先取得它的 device 的列表。這可以透過呼叫 clGetContextInfo 函式來取得。不過,因為我們一開始並不知道它有幾個 device,所以先呼叫第一次,並在最後一個參數傳入一個指標,以取得需要的記憶體大小。也就是: clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &cb); 配置好需要的記憶體之後,再呼叫第二次,才真正取得所要的資料內容,即: clGetContextInfo(context, CL_CONTEXT_DEVICES, cb, devices, 0); 在 OpenCL 中,很多取得資料的函式,都會使用到類似的方法。事實上,接下來取得 device 名稱的地方,就馬上又使用到了。 要取得 device 名稱,我們需要前面取得的 device 列表,把第一個 device(即 devices[0])傳入 clGetDeviceInfo 函式。clGetDeviceInfo 可以取得各種不同的 device 資訊,這裡我們要的是 CL_DEVICE_NAME,即 device 的名稱。和前面一樣,要先呼叫一次取得需要的記憶體大小,配置好記憶體後,再呼叫第二次以取得資料內容。 最後,把配置的記憶體釋放,並呼叫 clReleaseContext 函式,把之前建立的 OpenCL context 釋放,程式就結束了。 |
OpenCL >