成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一文說清OpenCL框架

開發 架構
OpenCL(Open Computing Language,開放計算語言):從軟件視角看,它是用于異構平臺編程的框架;從規范視角看,它是異構并行計算的行業標準,由Khronos Group來維護。

 [[414533]]

本文轉載自微信公眾號「LoyenWang」,作者LoyenWang。轉載本文請聯系LoyenWang公眾號。

背景

  • Read the fucking official documents! --By 魯迅
  • A picture is worth a thousand words. --By 高爾基

說明:

  • 對不起,我竟然用了一個奪人眼球的標題;
  • 我會盡量從一個程序員的角度來闡述OpenCL,目標是淺顯易懂,如果沒有達到這個效果,就當我沒說這話;
  • 子曾經曰過:不懂Middleware的系統軟件工程師,不是一個好碼農;

1. 介紹

  • OpenCL(Open Computing Language,開放計算語言):從軟件視角看,它是用于異構平臺編程的框架;從規范視角看,它是異構并行計算的行業標準,由Khronos Group來維護;
  • 異構平臺包括了CPU、GPU、FPGA、DSP,以及最近幾年流行的各類AI加速器等;
  • OpenCL包含兩部分:

1)用于編寫運行在OpenCL device上的kernels的語言(基于C99);

2)OpenCL API,至于Runtime的實現交由各個廠家,比如Intel發布的opencl_runtime_16.1.2_x64_rh_6.4.0.37.tgz

以人工智能場景為例來理解一下,假如在某個AI芯片上跑人臉識別應用,CPU擅長控制,AI processor擅長計算,軟件的flow就可以進行拆分,用CPU來負責控制視頻流輸入輸出前后處理,AI processor來完成深度學習模型運算完成識別,這就是一個典型的異構處理場景,如果該AI芯片的SDK支持OpenCL,那么上層的軟件就可以基于OpenCL進行開發了。

話不多說,看看OpenCL的架構吧。

2. OpenCL架構

OpenCL架構,可以從平臺模型、內存模型、執行模型、編程模型四個角度來展開。

2.1 Platform Model

平臺模型:硬件拓撲關系的抽象描述

  • 平臺模型由一個Host連接一個或多個OpenCL Devices組成;
  • OpenCL Device,可以劃分成一個或多個計算單元Compute Unit(CU);
  • CU可以進一步劃分成一個或多個處理單元Processing Unit(PE),最終的計算由PE來完成;
  • OpenCL應用程序分成兩部分:host代碼和device kernel代碼,其中Host運行host代碼,并將kernel代碼以命令的方式提交到OpenCL devices,由OpenCL device來運行kernel代碼;

2.2 Execution Model

執行模型:Host如何利用OpenCL Device的計算資源完成高效的計算處理過程

Context

OpenCL的Execution Model由兩個不同的執行單元定義:1)運行在OpenCL設備上的kernel;2)運行在Host上的Host program;其中,OpenCL使用Context代表kernel的執行環境:

Context包含以下資源:

  • Devices:一個或多個OpenCL設備;
  • Kernel Objects:OpenCL Device的執行函數及相關的參數值,通常定義在cl文件中;
  • Program Objects:實現kernel的源代碼和可執行程序,每個program可以包含多個kernel;
  • Memory Objects:Host和OpenCL設備可見的變量,kernel執行時對其進行操作;

NDrange

  • kernel是Execution Model的核心,放置在設備上執行,當kernel執行前,需要創建一個索引空間NDRange(一維/二維/三維);
  • 執行kernel實例的稱為work-item,work-item組織成work-group,work-group組織成NDRange,最終將NDRange映射到OpenCL Device的計算單元上;

有兩種方式來找到work-item:

  1. 通過work-item的全局索引;
  2. 先查找到所在work-group的索引號,再根據局部索引號確定;

以一維為例:

  • 上圖中總共有四個work-group,每個work-group包含四個work-item,所以local_size的大小為4,而local_id都是從0開始重新計數;
  • global_size代表總體的大小,也就是16個work-item,而global_id則是從0開始計數;

以二維為例:

  • 二維的計算方式與一維類似,也是結合global和local的size,可以得出global_id和local_id的大小,細節不表了;

三維的方式也類似,略去。

2.3 Memory Model

內存模型:Host和OpenCL Device怎么來看待數據

OpenCL的內存模型中,包含以下幾類類型的內存:

  • Host memory:Host端的內存,只能由Host直接訪問;
  • Global Memory:設備內存,可以由Host和OpenCL Device訪問,允許Host的讀寫操作,也允許OpenCL Device中PE讀寫,Host負責該內存中Buffer的分配和釋放;
  • Constant Global Memory:設備內存,允許Host進行讀寫操作,而設備只能進行讀操作,用于傳輸常量數據;
  • Local Memory:單個CU中的本地內存,Host看不到該區域并無法對其操作,該區域允許內部的PE進行讀寫操作,也可以用于PE之間的共享,需要注意同步和并發問題;
  • Private Memory:PE的私有內存,Host與PE之間都無法看到該區域;

2.4 Programming Model

  • 在編程模型中,有兩部分代碼需要編寫:一部分是Host端,一部分是OpenCL Device端;
  • 編程過程中,核心是要維護一個Context,代表了整個Kernel執行的環境;
  • 從cl源代碼中創建Program對象并編譯,在運行時創建Kernel對象以及內存對象,設置好相關的參數和輸入之后,就可以將Kernel送入到隊列中執行,也就是Launch kernel的流程;
  • 最終等待運算結束,獲取計算結果即可;

3. 編程流程

  • 上圖為一個OpenCL應用開發涉及的基本過程;

下邊來一個實際的代碼測試跑跑,Talk is cheap, show me the code!

4. 示例代碼

  • 測試環境:Ubuntu16.04,安裝Intel CPU OpenCL SDK(opencl_runtime_16.1.2_x64_rh_6.4.0.37.tgz);
  • 為了簡化流程,示例代碼都不做容錯處理,僅保留關鍵的操作;
  • 整個代碼的功能是完成向量的加法操作;

4.1 Host端程序

  1. #include <iostream> 
  2. #include <fstream> 
  3. #include <sstream> 
  4.  
  5. #include <CL/cl.h> 
  6.  
  7. const int DATA_SIZE = 10; 
  8.  
  9. int main(void) 
  10.     /* 1. get platform & device information */ 
  11.     cl_uint num_platforms; 
  12.     cl_platform_id first_platform_id; 
  13.     clGetPlatformIDs(1, &first_platform_id, &num_platforms); 
  14.  
  15.  
  16.     /* 2. create context */ 
  17.     cl_int err_num; 
  18.     cl_context context = nullptr; 
  19.     cl_context_properties context_prop[] = { 
  20.         CL_CONTEXT_PLATFORM, 
  21.         (cl_context_properties)first_platform_id, 
  22.         0 
  23.     }; 
  24.     context = clCreateContextFromType(context_prop, CL_DEVICE_TYPE_CPU, nullptr, nullptr, &err_num); 
  25.  
  26.  
  27.     /* 3. create command queue */ 
  28.     cl_command_queue command_queue; 
  29.     cl_device_id *devices; 
  30.     size_t device_buffer_size = -1; 
  31.  
  32.     clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, nullptr, &device_buffer_size); 
  33.     devices = new cl_device_id[device_buffer_size / sizeof(cl_device_id)]; 
  34.     clGetContextInfo(context, CL_CONTEXT_DEVICES, device_buffer_size, devices, nullptr); 
  35.     command_queue = clCreateCommandQueueWithProperties(context, devices[0], nullptr, nullptr); 
  36.     delete [] devices; 
  37.  
  38.  
  39.     /* 4. create program */ 
  40.     std::ifstream kernel_file("vector_add.cl", std::ios::in); 
  41.     std::ostringstream oss; 
  42.  
  43.     oss << kernel_file.rdbuf(); 
  44.     std::string srcStdStr = oss.str(); 
  45.     const char *srcStr = srcStdStr.c_str(); 
  46.     cl_program program; 
  47.     program = clCreateProgramWithSource(context, 1, (const char **)&srcStr, nullptr, nullptr); 
  48.  
  49.  
  50.     /* 5. build program */ 
  51.     clBuildProgram(program, 0, nullptr, nullptr, nullptr, nullptr); 
  52.  
  53.  
  54.     /* 6. create kernel */ 
  55.     cl_kernel kernel; 
  56.     kernel = clCreateKernel(program, "vector_add", nullptr); 
  57.  
  58.  
  59.     /* 7. set input data && create memory object */ 
  60.     float output[DATA_SIZE]; 
  61.     float input_x[DATA_SIZE]; 
  62.     float input_y[DATA_SIZE]; 
  63.     for (int i = 0; i < DATA_SIZE; i++) { 
  64.         input_x[i] = (float)i; 
  65.         input_y[i] = (float)(2 * i); 
  66.     } 
  67.  
  68.     cl_mem mem_object_x; 
  69.     cl_mem mem_object_y; 
  70.     cl_mem mem_object_output; 
  71.     mem_object_x = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float) * DATA_SIZE, input_x, nullptr); 
  72.     mem_object_y = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float) * DATA_SIZE, input_y, nullptr); 
  73.     mem_object_output = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float) * DATA_SIZE, nullptr, nullptr); 
  74.  
  75.  
  76.     /* 8. set kernel argument */ 
  77.     clSetKernelArg(kernel, 0, sizeof(cl_mem), &mem_object_x); 
  78.     clSetKernelArg(kernel, 1, sizeof(cl_mem), &mem_object_y); 
  79.     clSetKernelArg(kernel, 2, sizeof(cl_mem), &mem_object_output); 
  80.  
  81.  
  82.     /* 9. send kernel to execute */ 
  83.     size_t globalWorkSize[1] = {DATA_SIZE}; 
  84.     size_t localWorkSize[1] = {1}; 
  85.     clEnqueueNDRangeKernel(command_queue, kernel, 1, nullptr, globalWorkSize, localWorkSize, 0, nullptr, nullptr); 
  86.  
  87.  
  88.     /* 10. read data from output */ 
  89.     clEnqueueReadBuffer(command_queue, mem_object_output, CL_TRUE, 0, DATA_SIZE * sizeof(float), output, 0, nullptr, nullptr); 
  90.     for (int i = 0; i < DATA_SIZE; i++) { 
  91.         std::cout << output[i] << " "
  92.     } 
  93.     std::cout << std::endl; 
  94.  
  95.  
  96.     /* 11. clean up */ 
  97.     clRetainMemObject(mem_object_x); 
  98.     clRetainMemObject(mem_object_y); 
  99.     clRetainMemObject(mem_object_output); 
  100.     clReleaseCommandQueue(command_queue); 
  101.     clReleaseKernel(kernel); 
  102.     clReleaseProgram(program); 
  103.     clReleaseContext(context); 
  104.  
  105.     return 0; 

4.2 OpenCL Kernel函數

  • 在Host程序中,創建program對象時會去讀取kernel的源代碼,本示例源代碼位于:vector_add.cl文件中

內容如下:

  1. __kernel void vector_add(__global const float *input_x, 
  2.  __global const float *input_y, 
  3.  __global float *output
  4.  int gid = get_global_id(0); 
  5.   
  6.  output[gid] = input_x[gid] + input_y[gid]; 

4.3 輸出

參考

The OpenCL Specification

責任編輯:武曉燕 來源: LoyenWang
相關推薦

2021-12-15 09:32:41

Linux系統負載

2020-05-11 07:57:33

區塊鏈分布式鏈上

2023-01-26 01:09:31

配置數據源參數

2021-09-15 06:55:34

異步LinqC#

2021-01-27 08:12:04

Dotnet函數數據

2025-02-19 10:49:24

2022-04-28 10:41:08

SaaS業務方式

2019-11-12 15:11:45

秒殺流量高可用

2018-05-22 10:09:09

數據庫MySQL優化原理

2021-04-14 07:47:59

AttributeC#屬性

2019-01-29 09:36:10

MySQLACID特性

2024-02-22 14:20:44

數字化轉型數字化

2019-11-27 09:32:46

API 網關微服務

2022-04-12 10:34:05

Web框架方案

2024-09-18 13:57:15

2025-04-22 08:57:27

2024-05-27 00:45:00

2023-03-28 07:51:56

CPU主板平臺

2025-04-30 10:36:17

2017-05-05 12:59:00

大數據物聯網安全
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91精品国产综合久久久动漫日韩 | 国产高清精品一区二区三区 | 一级a爱片性色毛片免费 | 欧美日韩视频一区二区 | 成人亚洲 | 91免费在线 | 日韩视频国产 | 精品国产免费一区二区三区五区 | 中文字幕1区2区3区 日韩在线视频免费观看 | 亚洲精品免费在线 | 99精品欧美一区二区三区综合在线 | 日韩在线免费 | 欧美三级成人理伦 | 亚洲欧美精| 亚洲欧美精品 | 天天看天天操 | 99视频免费在线观看 | 国产一区二区三区视频免费观看 | 国产综合久久久久久鬼色 | 日韩欧美视频 | 色视频成人在线观看免 | 一区二区三区中文字幕 | 波多野结衣中文字幕一区二区三区 | 中文字幕亚洲视频 | 一本一道久久a久久精品蜜桃 | 日韩国产精品一区二区三区 | 日韩欧美视频 | 精品视频在线观看 | 欧美日韩综合 | 日韩在线欧美 | 亚洲自拍偷拍av | 五月综合激情在线 | 亚洲精品电影网在线观看 | 狠狠操狠狠操 | 在线伊人网 | 亚洲品质自拍视频网站 | 国产夜恋视频在线观看 | 久久国产成人 | 国产日韩免费观看 | 亚洲一二三在线观看 | 黄色大片在线免费观看 |