天天看點

OpenCL 通用程式設計與優化(18)

OpenCL 通用程式設計與優化(18)

        • 9.3.5.3圖像寫入
      • 9.3.6壓縮圖像支援
    • 9.4在Adrenogpu上的機器學習
      • 9.4.1高通神經處理SDK(SNPE/QNN)
      • 9.4.2 OpenCL ML SDK的Adrenogpu
      • 9.4.3張量虛拟機(TVM)和cl_qcom_ml_ops擴充
        • 9.4.3.1為什麼TVM
        • 9.4.3.2TVM如何與cl_qcom_ml_ops擴充一起工作
        • 9.4.3.3如何使用cl_qcom_ml_ops擴充使用TVM
      • 9.4.4針對ML的其他功能
        • 9.4.4.1支援bfloat16資料

9.3.5.3圖像寫入

在Adrenogpu中支援一組新的内置的向量圖像寫函數,使用命名約定作為qcom_write_image##datatypev_##pattern_suffix##_format_suffix##,。函數名稱顯式地指定它所支援的圖像格式、向量格式以及目标圖像的格式和平面。圖像寫入函數有很多種形式。以下是以下幾個例子:

qcom_write_imagefv_2x1_n8n00(image2d_t image, int2 coord, float 
color[2])
qcom_write_imagefv_2x1_n8n01(image2d_t image, int2 coord, float2 
color[2])
qcom_write_imagefv_2x1_n10p00(image2d_t image, int2 coord, float 
color[2])
qcom_write_imagehv_3x1_n10t00(image2d_t image, int2 coord, half 
color[3])
qcom_write_imageuiv_4x1_u10m00(image2d_t image, int2 coord, uint 
color[4])
           

一些函數需要特定的圖像格式,如NV12_Y和TP10_UV。僅Y圖像和僅紫外線圖像是多平面平面圖像的單平面導數。它們可以通過使用cl_qcom_extract_image_plane擴充來建立。

重要的是要了解這些函數必須與支援的圖像類型和資料類型一起使用。否則,傳回值将未定義。例如,用來讀取浮點函數的函數qcom_read_imagef_2x2和qcom_read_imagef_4x1隻支援使用CL_FLOAT、CL_HALF_FLOAT、CL_UNORM_XX和CL_QCOM_UNORM_INT10等格式建立的圖像。對于YUV格式的圖像的向量讀寫有一些特殊的規則:

  • 4x1讀取U或V值的結果将傳回與所選Y像素對應的U或V值。
    • 以Y00為中心的U平面的4x1讀取将傳回(U00、U00、U01、U01),與四個Y值對應的四個U值。
  • U或V平面的2x2讀取傳回四個不同的U或V值。例如,參考下面的4x4圖像:
    • 以同一點為中心的2x2讀取将傳回(U10、U11、U01、U00)。
      OpenCL 通用程式設計與優化(18)
      圖9-7 YUV圖像的向量讀寫圖

9.3.6壓縮圖像支援

Adrenogpu支援一個名為cl_qcom_compressed_image的擴充,它允許用高通公司設計的專有壓縮格式讀取和寫入圖像。除了節省記憶體帶寬外,它還可以降低功率和能量消耗,這對許多相機和視訊用例特别有用,因為它們通常對資料的要求非常高。要使用擴充,主機必須使用表9-4中的函數來查詢格式可用性以及通道和資料類型支援資訊,因為它們在不同的Adrenogpu之間可能會有所不同。使用壓縮圖像格式的方法與正常圖像格式相似:

  • 它支援兩種過濾模式,CLK_FILTER_LINEAR和CLK_FILTER_NEAREST。
  • 它支援幾個不同的圖像通道,如CL_RGBA。
  • 它支援資料類型,如CL_UNORM_INT8。

使用壓縮格式的一個典型用例和工作流程是讓GPU讀取由SOC中的其他子產品(如相機子產品)産生的壓縮資料。這通常與零複制技術相結合(例如,使用ION記憶體或Android本機緩沖區技術)相結合。表9-4顯示了這兩種方法的步驟,除了一些标志和枚舉類型外,這兩種方法非常相似。

表9-4使用壓縮圖像的步驟

Step ION Android Native buffer
查詢支援的格式 errcode = clGetSupportedImageFormats(context, CL_MEM_READ_ONLY CL_MEM_COMPRESSED_IMAGE_QCOM, CL_MEM_OBJECT_IMAGE2D, num_format_list_entries, format_list, &num_reported_image_formats);
建立一個緩沖區來儲存圖像資料 cl_mem_ion_host_ptrcompressed_ionmem = {0}; // Initialize ION buffer attributes compressed_ionmem.ext_host_ptr.allocation_type = CL_MEM_ION_HOST_PTR_QCOM;compressed_ionmem.ext_host_ptr.host_cache_policy =CL_MEM_HOST_UNCACHED_QCOM; compressed_ionmem.ion_filedesc = ion_info_fd.file_descriptor; // file descriptor for ION compressed_ionmem.ion_hostptr = ion_info.host_virtual_address; // hostptr returned by ION cl_mem_android_native_buffer_host_ptrcompressed_ANBmem = {0};GraphicBuffer *gb; // previously created compressed_ANBmem.ext_host_ptr.allocation_type = CL_MEM_ANDROID_NATIVE_BUFFER_HOST_PTR_QCOM; compressed_ANBmem.ext_host_ptr.host_cache_policy = CL_MEM_HOST_WRITEBACK_QCOM; // the hostptr to a native buffer and gb is an Android GraphicBuffer compressed_ANBmem.anb_ptr = gb->getNativeBuffer();
建立一個可供應用程式使用的圖像對象 cl_image_format image_format = {0}; cl_image_desc image_desc = {0}; cl_int errcode = 0; // Set image format image_format- >image_channel_order = CL_QCOM_COMPRESSED_RGBA; image_format- >image_channel_data_type = CL_UNORM_INT8; // Set image parameters image_desc->image_width = 128; image_desc->image_height = 256; image_desc->image_row_pitch = 0; // must be 0 for compressed images image_desc->image_slice_pitch = 0; // must be 0 for compressed images // Create a compressed image compressed_rbga_image =clCreateImage (context, CL_MEM_EXT_HOST_PTR_QCOM CL_MEM_READ_ONLY, image_format, image_desc, (void*)compressed_ionmem, &errcode); cl_image_format image_format = {0}; cl_image_desc image_desc = {0}; cl_int errcode = 0; // Set image format image_format- >image_channel_order = CL_QCOM_COMPRESSED_RGBA; image_format- >image_channel_data_type = CL_UNORM_INT8; // Set image parameters image_desc->image_width = 128; image_desc->image_height = 256; image_desc->image_row_pitch = 0; // always 0 for compressed images image_desc->image_slice_pitch = 0; // always 0 for compressed images // Create a compressed image compressed_rbga_image = clCreateImage (context, CL_MEM_EXT_HOST_PTR_QCOM

在Adrenogpu上的OpenCL可以解碼和讀取一個壓縮圖像,并将其以相同的壓縮格式寫入另一個圖像。但是,壓縮後的圖像隻能在核心中讀取或寫入。就位讀/寫特性,即CL_MEM_KERNEL_READ_AND_WRITE不支援壓縮圖像。

9.4在Adrenogpu上的機器學習

9.4.1高通神經處理SDK(SNPE/QNN)

高通神經處理SDK(SNPE/QNN)是一個成熟的ML工作負載的解決方案。專有的、閉源代碼的SDK已經取得了巨大的成功。它為客戶提供了一套大型的工具和SDKs,通過使用骁龍上所有可用的計算裝置來加速神經網絡,包括CPU、GPU和DSP。制造商和開發商采用了神經處理SDK。

一些進階開發人員仍然更傾向于專門在Adrenogpu上運作他們的ML工作負載。他們可以利用最近釋出的高通Adreno OpenCL ML SDK,在Adrenogpu上進行定制、靈活性和加速。

9.4.2 OpenCL ML SDK的Adrenogpu

開發人員可以通過cl_qcom_ml_ops擴充來加速許多常見的機器學習操作。高通優化的操作可以提供一個顯著的性能優勢。他們同時支援推理和訓練。更多的細節可從部落格:Openo機器學習加速Adreno GPU -Qualcomm Developer Network.。以下是SDK的一些元素:

  • 是一個OpenCL擴充,cl_qcom_ml_ops,是SDK的核心部分。該擴充可在一些AdrenoA6xGPU和所有A7xgpu中使用,它提供了一組全面的API函數,以支援許多關鍵的ML操作。
  • 這些功能包含了高度優化的核心,充分利用了AdrenoGPU的硬體能力。
  • 除了API函數之外,該擴充還定義了所需的資料結構、标記、張量對象和記憶體管理機制,以友善使用API函數。
  • SDK還提供了一個模型轉換工具,将使用标準ML網絡的模型檔案,如張量Flow和PyTorch,轉換為api可以在ML擴充中直接使用的模型。
  • 有了SDK,開發人員可以輕松地使用ML Ops來移植和調整他們的ML應用程式開發人員,而不是編寫他們的OpenCL核心,這可能會提高性能。請參閱SDK文檔和代碼示例,以了解更多細節。

9.4.3張量虛拟機(TVM)和cl_qcom_ml_ops擴充

最近,TVM,一個著名的、非常活躍的用于深度學習工作負載的開源編譯器架構,已經增加了對Adreno的cl_qcom_ml_ops擴充的支援。它降低了開發人員使用SDK的門檻,并幫助提供了一個在Adrenogpu上運作的ML網絡的快速生成和原型化。

9.4.3.1為什麼TVM

TVM可以為給定的ML操作或層自動生成幾個OpenCL核心實作。然後,它可以使用基于ml的調優方法從較大的搜尋空間中找到性能最好的OpenCL核心。TVM可以對ML模型進行操作級和圖形級優化,進而為廣泛的硬體子產品生成高性能的OpenCL核心實作。而且,由于它是開源的,TVM得到了一個活躍的大型社群的支援,其成員來自業界和學術界。

9.4.3.2TVM如何與cl_qcom_ml_ops擴充一起工作

TVM社群已經引入了BYOC,作為将來自供應商加速庫(如Adreno)中的高性能核心嵌入到由TVM生成的主代碼中的一種方法。是以,我們正在利用BYOC将cl_qcom_ml_ops擴充內建到TVM中,以實作端到端解決方案。

盡管cl_qcom_ml_ops擴充功能強大,但它的專有api帶有一個學習曲線。TVM和cl_qcom_ml_ops的內建比單獨使用SDK更簡單。通過這種內建,開發人員不需要了解規範、頭檔案或要調用哪些api。它允許開發人員在第一天就開始使用OpenCL ML,而不了解API的定義。

9.4.3.3如何使用cl_qcom_ml_ops擴充使用TVM

Adreno OpenCL ML內建到TVM中已經是開源和流的。該內建允許開發人員輕松地從TVM支援的架構中導入深度學習模型,如張量流、PyTorch、Keras、CoreML、MXnet和ONNX。它盡可能多地使用TVM和Adreno OpenCL ML庫核心的圖級優化。對于cl_qcom_ml_ops擴充不支援的任何核心或操作符,BYOC允許為TVM支援的任何後端提供回退選項。

更多細節請參閱OpenCL ML SDK和部落格:使用TVM和AdrenoOpenCLMLapi加速您的機器學習網絡的速度。

9.4.4針對ML的其他功能

9.4.4.1支援bfloat16資料

bfloat16(大腦浮點)浮點格式使用16位,通過保留8個指數位來表示32位浮點數的近似動态範圍。不過,它隻支援8位的精度,而不是24位的FP32格式。bfloat16可以用來減少資料存儲需求,也可以加速一些機器學習算法。有關更多資訊,請參閱Adreno OpenCL SDK。

繼續閱讀