CUDA C++编程接口:编译
CUDA C++編程接口:編譯
一.概述
CUDA C++為熟悉C++編程語言的用戶提供了一個簡單的路徑,以方便地編寫程序以執行該設備。
它由一組最小的擴展到C++語言和運行庫。
在編程模型中引入了核心語言擴展。它們允許程序員定義內核作為C++函數,并使用一些新的語法來指定每次調用函數時的網格和塊維數。所有擴展的完整描述可以在C++語言擴展中找到。任何包含這些擴展名的源文件都必須使用nvcc編譯,如使用nvcc編譯中所述。在CUDA運行時中引入了運行時。它提供了在主機上執行的C和C++函數,分配和釋放設備存儲器,在主機內存和設備內存之間傳輸數據,管理多個設備的系統等。運行時的完整描述可以在CUDA參考手冊中找到。
運行時構建在較低級別的C API(CUDA驅動程序API)之上,應用程序也可以訪問該API。驅動程序API通過公開較低級別的概念(如CUDA上下文,設備的主機進程模擬)和CUDA模塊(設備的動態加載庫模擬),提供了額外的控制級別。大多數應用程序不使用驅動程序API,因為它們不需要這種額外的控制級別,并且在使用運行時,上下文和模塊管理是隱式的,從而產生更簡潔的代碼。由于運行時可以與驅動程序API互操作,因此大多數需要一些驅動程序API特性的應用程序都可以默認使用運行時API,并且只在需要時使用驅動程序API。驅動程序API在驅動程序API中介紹,并在參考手冊中詳細描述。
二.用NVCC編譯
內核可以使用CUDA指令集體系結構(稱為PTX)編寫,PTX參考手冊中對此進行了描述。然而,通常使用C++等高級編程語言更有效。在這兩種情況下,內核都必須由nvcc編譯成二進制代碼才能在設備上執行。
NVCC是一個編譯器驅動程序,簡化了編譯C++或PTX代碼的過程:它提供了簡單而熟悉的命令行選項,并通過調用實現不同編譯階段的工具集合來執行它們。本節概述了nvcc工作流和命令選項。完整的描述可以在nvcc用戶手冊中找到。
2.1.編譯工作流
2.1.1. 脫機編譯
用nvcc編譯的源文件可以包括主機代碼(即,在主機上執行的代碼)和設備代碼(即,在設備上執行的代碼)的混合。nvcc的基本工作流程是將設備代碼與主機代碼分,將設備代碼編譯為匯編形式(PTX代碼)和/或二進制形式(cubin對象),并通過用必要的CUDA運行時函數調用替換內核中引入的語法(并在執行配置中詳細描述)來修改宿主代碼,以便從PTX代碼和/或cubin對象加載和啟動每個編譯的內核。
將修改后的主機代碼輸出為C++代碼,該代碼將被另一個工具編譯或直接作為對象代碼,通過NVCC在最后編譯階段調用宿主編譯器。
應用程序,鏈接到已編譯的主機代碼(這是最常見的情況),或者忽略修改后的主機代碼(如果有的話),并使用CUDA驅動程序API(請參閱驅動程序API)來加載和執行PTX代碼或cubin對象。
2.1.2.即時編譯
應用程序在運行時加載的任何PTX代碼都由設備驅動程序進一步編譯為二進制代碼。這稱為即時編譯。即時編譯增加了應用程序加載時間,但允許應用程序從每個新設備驅動程序帶來的任何新編譯器改進中獲益。這也是應用程序在編譯應用程序時不存在的設備上運行的唯一方法,如應用程序兼容性中所述。
當設備驅動程序及時為某個應用程序編譯一些PTX代碼時,它會自動緩存生成的二進制代碼的副本,以避免在隨后的應用程序調用中重復編譯。當設備驅動程序升級時,緩存(稱為計算緩存)會自動失效,因此應用程序可以從設備驅動程序中內置的新實時編譯器的改進中獲益。
環境變量可用于控制CUDA環境變量中描述的實時編譯
作為使用NVCC來編譯CUDA C++設備代碼的替代方案,NVRTC可以用于在運行時編譯CUDA C++設備代碼到PTX。NVRTC是CUDA C++的運行時編譯庫;NVRTC用戶指南中可以找到更多信息。
2.2.二進制兼容性
二進制代碼是特定于體系結構的。cubin對象是使用指定目標體系結構的編譯器選項-code生成的:例如,使用-code=sm_35編譯會為具有計算能力3.5的設備生成二進制代碼。二進制兼容性保證從一個小版本到下一個小版本,但不是從一個小版本到上一個小版本或跨主要版本。換句話說,為計算能力X.y生成的cubin對象將只在計算能力X.z的設備上執行,其中z≥y。
注意:僅桌面支持二進制兼容性。Tegra不支持此功能。桌面和Tegra之間的二進制兼容性也不受支持。
2.3.PTX兼容性
某些PTX指令僅在具有更高計算能力的設備上受支持。例如,Warp Shuffle函數僅在計算能力為3.0及以上的設備上受支持。-ARCH編譯器選項指定編譯C++到PTX代碼時所假定的計算能力。例如,包含warp shuffle的代碼必須使用-arch=compute_(或更高版本)編譯。為某些特定計算能力生成的PTX代碼始終可以編譯為具有更大或同等計算能力的二進制代碼。請注意,從早期PTX版本編譯的二進制文件可能無法使用某些硬件功能。例如,從為計算能力6.0(Pascal)生成的PTX編譯的計算能力7.0(Volta)的二進制目標設備將不會使用張量核心指令,因為這些指令在Pascal上不可用。因此,最終的二進制文件的性能可能比使用最新版本的PTX生成的二進制文件的性能差。
2.4.應用程序兼容性
要在具有特定計算能力的設備上執行代碼,應用程序必須加載與此計算能力兼容的二進制或PTX代碼,如二進制兼容性和PTX兼容性中所述。特別是,為了能夠在具有更高計算能力的未來體系結構上執行代碼(還不能生成二進制代碼),應用程序必須加載將為這些設備及時編譯的PTX代碼(請參閱及時編譯)。
在NUCC用戶手冊中詳細說明了在CUDA C++應用程序中嵌入的PTX和二進制代碼是由-ARCH和-CODER編譯器選項或-GEnCODE編譯器選項控制的。例如,
nvcc x.cu
-gencode arch=compute_35,code=sm_35
-gencode arch=compute_50,code=sm_50
-gencode arch=compute_60, code=‘compute_60,sm_60’
嵌入與計算能力3.5和5.0兼容的二進制代碼(第一和第二gencode選項)以及與計算能力6.0兼容的PTX和二進制代碼(第三gencode選項)。
生成宿主代碼是為了在運行時自動選擇要加載和執行的最合適的代碼,在上面的示例中,將是:
3.5計算能力為3.5和3.7的設備的二進制代碼,
5.0計算能力為5.0和5.2的設備的二進制代碼,
6.0計算能力為6.0和6.1的設備的二進制代碼,
PTX代碼,在運行時為具有計算能力7.0及更高版本的設備編譯為二進制代碼。
x.cu可以有一個優化的代碼路徑,使用warp shuffle操作,例如,只有計算能力3.0及更高的設備才支持這種操作。根據計算能力,可以使用uda_uarch_uu宏來區分不同的代碼路徑。它只為設備代碼定義。例如,當使用-arch=compute_35編譯時,_uucuda_uarch_u等于350。
使用驅動程序API的應用程序必須編譯代碼以分離文件,并在運行時顯式加載和執行最合適的文件。
Volta架構引入了獨立的線程調度,它改變了GPU上線程的調度方式。對于依賴于以前架構中SIMT調度的特定行為的代碼,獨立的線程調度可能會改變參與線程的集合,從而導致錯誤的結果。為了幫助遷移,同時實現獨立線程調度中詳述的糾正操作,Volta開發人員可以選擇使用編譯器選項combination-arch=compute_-code=sm_來執行Pascal的線程調度。nvcc用戶手冊列出了-arch、-code和-gencode編譯器選項的各種縮寫。例如,-arch=sm_35是-arch=compute_35-code=compute_35,sm_35的縮寫(與-gencodearch=compute_35,code='compute_35,sm_35’相同)。
2.5. C++兼容性
編譯器的前端根據C++語法規則處理CUDA源文件。主機代碼支持完全C++。但是,C++語言支持中只支持一個C++子集。
2.6.
64位兼容性
64位版本的nvcc以64位模式編譯設備代碼(即指針為64位)。只有在64位模式下編譯的主機代碼才支持在64位模式下編譯的設備代碼。
類似地,
32位版本的nvcc以32位模式編譯設備代碼,而32位模式編譯的設備代碼僅支持以32位模式編譯的主機代碼。
32位版本的nvcc還可以使用-m64編譯器選項以64位模式編譯設備代碼。
64位版本的nvcc還可以使用-m32編譯器選項以32位模式編譯設備代碼。
總結
以上是生活随笔為你收集整理的CUDA C++编程接口:编译的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CUDA C++程序设计模型
- 下一篇: CUDA运行时 Runtime(一)