開始使用 cuda

CUDA 是用於其 GPU 的專有 NVIDIA 平行計算技術和程式語言。

GPU 是高度並行的機器,能夠並行執行數千個輕量級執行緒。每個 GPU 執行緒的執行速度通常較慢,而且其上下文較小。另一方面,GPU 能夠並行執行數千個執行緒,甚至更多併發執行(精確數量取決於實際的 GPU 模型)。CUDA 是專為 NVIDIA GPU 架構設計的 C++方言。但是,由於體系結構的不同,大多數演算法都不能簡單地從普通的 C++中複製貼上 - 它們會執行,但速度很慢。

術語

  • host - 指在該環境中執行的普通基於 CPU 的硬體和普通程式
  • device - 指 CUDA 程式執行的特定 GPU。單個主機可以支援多個裝置。
  • kernel - 駐留在可以從主機程式碼呼叫的裝置上的函式。

物理處理器結構

支援 CUDA 的 GPU 處理器具有以下物理結構:

  • 晶片 - GPU 的整個處理器。有些 GPU 有兩個。
  • 流式多處理器 (SM) - 每個晶片最多包含~100 個 SM,具體取決於型號。每個 SM 幾乎獨立於另一個 SM 執行,僅使用全域性儲存器相互通訊。
  • CUDA 核心 - SM 的單個標量計算單元。它們的確切數量取決於架構。每個核心可以快速連續地處理幾個併發執行的執行緒(類似於 CPU 中的超執行緒)。

此外,每個 SM 都具有一個或多個 warp 排程程式。每個排程程式將一條指令分派給多個 CUDA 核心。這有效地使 SM 在 32 寬 SIMD 模式下操作。

CUDA 執行模型

GPU 的物理結構直接影響核心在裝置上的執行方式,以及如何在 CUDA 中對它們進行程式設計。使用呼叫配置呼叫核心,該呼叫配置指定生成多少並行執行緒。

  • grid - 表示在核心呼叫時生成的所有執行緒。它被指定為一個或兩個維數的
  • - 是一組半獨立的執行緒。每個塊都分配給一個 SM。因此,塊只能通過全域性儲存器進行通訊。塊不以任何方式同步。如果塊太多,則一些塊可能在其他塊之後順序執行。另一方面,如果資源允許,可以在同一個 SM 上執行多個塊,但程式設計師無法從中發生這種情況(除了明顯的效能提升)。
  • 執行緒 - 由單個 CUDA 核心執行的標量序列指令。執行緒輕量級,具有最小的上下文,允許硬體快速交換它們。由於它們的數量,CUDA 執行緒執行時分配了幾個暫存器,並且堆疊非常短(最好是沒有!)。因此,CUDA 編譯器傾向於內聯所有函式呼叫以展平核心,使其僅包含靜態跳轉和迴圈。函式 ponter 呼叫和虛擬方法呼叫雖然在大多數較新的裝置中受支援,但通常會產生重大的效能問題。

每個執行緒由塊 blockIdx 中的塊索引 blockIdx 和執行緒索引標識。任何正在執行的執行緒都可以隨時檢查這些數字,這是區分一個執行緒與另一個執行緒的唯一方法。

此外,執行緒被組織成 warp ,每個 warp 包含 32 個執行緒。單個 warp 中的執行緒在 SIMD fahsion 中執行完美同步。來自不同 warp 但在同一塊中的執行緒可以按任何順序執行,但可以由程式設計師強制同步。來自不同塊的執行緒無法以任何方式同步或直接互動。

記憶組織

在正常的 CPU 程式設計中,記憶體組織通常對程式設計師是隱藏的。典型的程式就好像只有 RAM 一樣。所有記憶體操作(例如管理暫存器,使用 L1-L2-L3 快取,交換到磁碟等)都由編譯器,作業系統或硬體本身處理。

CUDA 的情況並非如此。雖然較新的 GPU 模型部分地隱藏了負擔,例如通過 CUDA 6 中的統一記憶體 ,但出於效能原因,仍然值得了解組織。基本的 CUDA 記憶體結構如下:

  • 主機記憶體 - 常規 RAM。主要由主機程式碼使用,但較新的 GPU 型號也可以訪問它。當核心訪問主機記憶體時,GPU 必須通常通過 PCIe 聯結器與主機板通訊,因此它相對較慢。
  • 裝置記憶體/全域性記憶體 - GPU 的主要片外記憶體,可供所有執行緒使用。
  • 共享記憶體 - 位於每個 SM 中,允許比全域性更快的訪問。共享記憶體對每個塊都是私有的。單個塊中的執行緒可以使用它進行通訊。
  • 暫存器 - 每個執行緒的最快,私有,無法定址的記憶體。通常,這些不能用於通訊,但是一些內在函式允許在經線內混洗它們的內容。
  • 本地記憶體 -每個執行緒的私有記憶體可定址。這用於暫存器溢位和具有可變索引的本地陣列。在物理上,它們存在於全域性記憶中。
  • 紋理記憶體,常量記憶體 - 全域性記憶體的一部分,標記為核心不可變。這允許 GPU 使用專用快取。
  • L2 快取 - 片上,可供所有執行緒使用。給定執行緒數量,每個快取行的預期生命週期遠低於 CPU。它主要用於輔助未對齊和部分隨機的記憶體訪問模式。
  • L1 快取 - 與共享記憶體位於同一空間。同樣,在給定使用它的執行緒數量的情況下,數量相當小,因此不要指望資料會長時間停留在那裡。可以禁用 L1 快取。