2019/08/25

make時にGPUのアーキテクチャ番号を自動設定させる方法

背景


複数種類の開発環境でまたがって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環境を構築する手順は、下記の通りである。
  1. check_cuda.cuをCMakeLists.txtと同じ階層に置く
  2. // 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 */
        }
    }
  3. CMakeLists.txtを編集する
  4. 下記のコードを追加することで、$CUDA_NVCC_FLAGSにコンパイルしたマシンのアーキテクチャを自動設定できる。
    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環境を構築する手順について調査、記載した

参考文献



変更履歴


  1. 2019/08/25: 新規作成

0 件のコメント:

コメントを投稿

MQTTの導入

背景 IoTデバイスの接続環境構築のため、MQTT(mosquitto)の導入を行った。 記事の目的 MQTT(mosquitto)をUbuntuに導入する mosquitto ここではmosquittoについて記載する。 MQTT MQTT(Message Qu...