背景
複数種類の開発環境でまたがってCUDAを利用したプログラムを開発する際、マシンに搭載されたGPUのアーキテクチャに応じて、CMakeLists.txt内のアーキテクチャ番号を毎回書き換える必要があった。メンテナンスの効率化のため、どのGPU搭載のマシンでmakeした場合でも、GPUの種類を識別して、そのGPUに最適なバイナリファイルを生成する環境を構築する。
記事の目的
makeする際に自動で搭載GPUのアーキテクチャを識別し、そのGPUに最適なバイナリーを出力するようにmake環境を構築する
仮想/実アーキテクチャの設定
ここでは、UbuntuにおけるマルチGPU対応のmake環境を構築するための方法について記載する。
nvccのコンパイルオプション
nvccのコンパイルオプションのうち、アーキテクチャに関する部分について記述する。- --gpu-architecture (-arch) *.cuが対象にしている仮想アーキテクチャを指定する。したがって、基本的にはcompute_*の中から選択する。
- --gpu-code (-code) 仮想アーキテクチャのコード(*.ptx)から生成して出力に加えるアーキテクチャを指定する。PTXを含めたいときはcompute_*、特定のGPU向けバイナリを含めたいときはsm_*を選択する。
- --generate-code arch=compute_*,code=\"compute_*,sm_*\" 上記2つのオプションを一度に設定できる
導入方法
make環境を構築する手順は、下記の通りである。- check_cuda.cuをCMakeLists.txtと同じ階層に置く
- CMakeLists.txtを編集する 下記のコードを追加することで、$CUDA_NVCC_FLAGSにコンパイルしたマシンのアーキテクチャを自動設定できる。
// check_cuda.cu
#include <stdio.h>
int main(int argc, char **argv){
cudaDeviceProp dP;
float min_cc = 3.0;
int rc = cudaGetDeviceProperties(&dP, 0);
if(rc != cudaSuccess) {
cudaError_t error = cudaGetLastError();
printf("CUDA error: %s", cudaGetErrorString(error));
return rc; /* Failure */
}
if((dP.major+(dP.minor/10)) < min_cc) {
printf("Min Compute Capability of %2.1f required: %d.%d found",
min_cc, dP.major, dP.minor);
printf(" Not Building CUDA Code");
return 1; /* Failure */
} else {
printf("%d%d", dP.major, dP.minor);
return 0; /* Success */
}
}
cmake_minimum_required(VERSION 3.0)
# Find CUDA
find_package(CUDA)
if (CUDA_FOUND)
#Get CUDA compute capability
set(OUTPUTFILE ${CMAKE_CURRENT_SOURCE_DIR}/cuda_script) # No suffix required
set(CUDAFILE ${CMAKE_CURRENT_SOURCE_DIR}/check_cuda.cu)
execute_process(COMMAND nvcc -lcuda ${CUDAFILE} -o ${OUTPUTFILE})
execute_process(COMMAND ${OUTPUTFILE}
RESULT_VARIABLE CUDA_RETURN_CODE
OUTPUT_VARIABLE ARCH)
execute_process(COMMAND rm ${OUTPUTFILE})
if(${CUDA_RETURN_CODE} EQUAL 0)
set(CUDA_SUCCESS "TRUE")
else()
set(CUDA_SUCCESS "FALSE")
endif()
if (${CUDA_SUCCESS})
message(STATUS "CUDA Architecture: -arch=sm_${ARCH}")
message(STATUS "CUDA Version: ${CUDA_VERSION_STRING}")
message(STATUS "CUDA Path: ${CUDA_TOOLKIT_ROOT_DIR}")
message(STATUS "CUDA Libararies: ${CUDA_LIBRARIES}")
message(STATUS "CUDA Performance Primitives: ${CUDA_npp_LIBRARY}")
set(CUDA_NVCC_FLAGS "{$CUDA_NVCC_FLAGS};--generate-code arch=compute_${ARCH},code=\"compute_${ARCH},sm_${ARCH}\"")
else()
message(WARNING -arch=sm_${ARCH})
endif()
endif()
まとめ
- 搭載GPUのアーキテクチャを識別し、そのGPUに最適なバイナリーを出力するmake環境を構築する手順について調査、記載した
参考文献
変更履歴
- 2019/08/25: 新規作成
0 件のコメント:
コメントを投稿