2014年4月25日 星期五

OpenCL: Query Platforms Info


since: 2014/04/25
update: 2014/04/25

reference:
1. Amazon.com: OpenCL Programming by Example
2. VIML-OpenCL 簡介
3. OpenCL 教學(一) - Hotball's Hive
4. Richard's blog: OpenCL 介紹
5. OpenCL - leon的专栏
6. Khronos 2013 - opencl_overview.pdf
7. OpenCL Programming Guide for Mac: About OpenCL for OS X
8. OpenCL 1.2 Reference Pages

A. 前言
     1. 本系列學習 OpenCL 的文章主要的參考來源是:
         a. 電子書: Amazon.com: OpenCL Programming by Example
         b. 網路文章

     2. 詳細的基本觀念說明, 請參考上方 reference 裡的文章.

     3. 以 OpenCL 1.2 為主要的版本.

---------------------------------------------------------------------------------------------

B. 測試環境 (只用貼圖, 越來越懶了我...)


---------------------------------------------------------------------------------------------

C. 相關觀念說明
     1. OpenCL Platform(平台)
         何謂 OpenCL Platform? 簡單來說, 就是不同的硬體廠商(ex: AMD, Intel,
         NVIDIA...)依照硬體架構所提供 OpenCL 實作framework / SDK,
         在 PC 上, 可以存在多個 OpenCL Platform, 而在 Mac 上只有一個.

     2. OpenCL Platform Model


         a. 主機上的 CPU 會與一個或多個 OpenCL devices(CPU, GPU, DSP...) 作連結.
             (A host is connected to one or more OpenCL devices)

         b. OpenCL device 聚集了一組或多組的計算單位.
             (OpenCL device is collection of one or more compute units)

         c. 一組計算單位是由一個或多個處理元素所組成
             (A compute unit is composed of one or more processing elements)

         d. 處理元素是以 "單一指令多筆資料" 或 "單一程序多筆資料" 的方式來執行程式碼.
             (Processing elements execute code as SIMD or SPMD)
             備註: SIMD: single Instruction, Multiple Data
                     SPMD: single program, multiple data


---------------------------------------------------------------------------------------------

D. 新增專案
     1. Xcode > File > New > Project...
         OS X > Application > Command Line Tool


     2. Choose options for your project:
         Product Name: HelloOpenCL
         Type: C++
          > Next

         備註: Type 可以選擇 C, 在這邊是預留以後可以加入 C++ 的程式

     3. 加入 OpenCL framework: OpenCL.framework


     4. 幫專案新增一個叫作 Utility 的群組: 
         > 在此群組內, 新增檔案: OpenCLHeader.h, QueryPlatformInfo.h
            與 QueryPlatformInfo.cpp

     5. 專案結構如下:


---------------------------------------------------------------------------------------------

E. 撰寫程式碼
     1. 標頭檔: 開啓 OpenCLHeader.h 檔案, 修改如下
/*
#ifndef HelloOpenCL_OpenCLHeader_h
#define HelloOpenCL_OpenCLHeader_h

#endif

*/

//@add
#include <stdio.h>
#include <stdlib.h>
#ifdef __APPLE__
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif


*************************************************************


     2. 開啓 QueryPlatformInfo.h 檔案, 修改如下
/*
#ifndef HelloOpenCL_QueryPlatformInfo_h
#define HelloOpenCL_QueryPlatformInfo_h

#endif

*/

//@add
#include "OpenCLHeader.h"

void PrintPlatformInfo(cl_platform_id platform);


*************************************************************

     3. 開啓 QueryPlatformInfo.cpp 檔案, 修改如下
#include "QueryPlatformInfo.h"

//@add
void PrintPlatformInfo(cl_platform_id platform)
{
    char queryBuffer[1024];
    cl_int clError;
   
    clError = clGetPlatformInfo (platform, CL_PLATFORM_NAME, 1024, &queryBuffer, NULL);
    if(clError == CL_SUCCESS)
    {
        printf("CL_PLATFORM_NAME   : %s\n", queryBuffer);
    }

    clError = clGetPlatformInfo (platform, CL_PLATFORM_VENDOR, 1024, &queryBuffer, NULL);
    if(clError == CL_SUCCESS)
    {
        printf("CL_PLATFORM_VENDOR : %s\n", queryBuffer);
    }

    clError = clGetPlatformInfo (platform, CL_PLATFORM_VERSION, 1024, &queryBuffer, NULL);
    if (clError == CL_SUCCESS)
    {
        printf("CL_PLATFORM_VERSION: %s\n", queryBuffer);
    }

    clError = clGetPlatformInfo (platform, CL_PLATFORM_PROFILE, 1024, &queryBuffer, NULL);
    if (clError == CL_SUCCESS)
    {
        printf("CL_PLATFORM_PROFILE: %s\n", queryBuffer);
    }

    clError = clGetPlatformInfo (platform, CL_PLATFORM_EXTENSIONS, 1024, &queryBuffer, NULL);
    if (clError == CL_SUCCESS)
    {
        printf("CL_PLATFORM_EXTENSIONS: %s\n", queryBuffer);
    }

    return;
}


*************************************************************


     4. 開啓 main.cpp 檔案, 修改如下
//#include <iostream>
//@add
#include "QueryPlatformInfo.h"


int main(int argc, const char * argv[])
{
    // insert code here...
    //std::cout << "Hello, World!\n";

   
    //@add
    cl_int           clError;
    cl_platform_id *platforms = NULL;
    cl_uint          num_platforms;

    // Get the number of Platforms available
    // Note that the second parameter "platforms" is set to NULL.
    // If this is NULL then this argument is ignored
    // and the API returns the total number of OpenCL platforms available. 

    // 先呼叫 clGetPlatformIDs, 以得到 num_platforms 的值
    clError = clGetPlatformIDs(0, NULL, &num_platforms);
    if(clError != CL_SUCCESS)
    {
        printf("Error in call to clGetPlatformIDs....\n Exiting");
        exit(0);
    }
    else
    {
        if (num_platforms == 0)
        {
            printf("No OpenCL Platforms Found ....\n Exiting");
        }
        else
        {
            //Allocate memory for OpenCL platforms.
            printf ("Found %d Platforms\n", num_platforms);
            platforms = (cl_platform_id *)malloc(num_platforms * sizeof(cl_platform_id));

            // Get the platform id's
            // In contrast to the above call with "platforms" as NULL. The below call actually fills the buffer with
            // the platform IDs. It will list the platforms upto the value specified by num_platforms. One should make
            // sure that the appropriate buffer size is allocated.
           
            // 
再次呼叫 clGetPlatformIDs, 得到 platforms 的值           
            clError = clGetPlatformIDs (num_platforms, platforms, NULL);


            // for each platform now start printing the information

            for(cl_uint index = 0; index < num_platforms; index++)
            {
                printf("==================Platform No %d======================\n",index);
                PrintPlatformInfo(platforms[index]);
                printf("======================================================\n\n");
            }
        }
    }
   
    return 0;
}

---------------------------------------------------------------------------------------------

F. 執行結果: