2015年5月24日日曜日

NVAPIを使ってGPUの各種情報を取得する

前のエントリNVAPIを使ってGPUの使用メモリ量を求めるでメモリ量を取得したが、それ以外の情報も取得してみる。

GPU温度の取得
  // 物理GPUハンドルは取得済みであるものとする
  NvPhysicalGpuHandle hPhysicalGpu = ...
  NvS32 temperature = 0;
  NvAPI_Status nv_status = NVAPI_OK;
  NV_GPU_THERMAL_SETTINGS thermal = {0,};
  thermal.version = NV_GPU_THERMAL_SETTINGS_VER;
  nv_status = NvAPI_GPU_GetThermalSettings( hPhysicalGpu, 0, &thermal );
  if ( nv_status == NVAPI_OK ) {
    if ( temp != NULL ) {
      for ( size_t i=0; i<NVAPI_MAX_THERMAL_SENSORS_PER_GPU; i++ ) {
        // targetがNVAPI_THERMAL_TARGET_GPUかどうかチェック
        if ( thermal.sensor[i].target == NVAPI_THERMAL_TARGET_GPU ) {
          temperature = thermal.sensor[i].currentTemp;
          break;
        }
      }
    }
  }

GPU使用率の取得
  // 物理GPUハンドルは取得済みであるものとする
  NvPhysicalGpuHandle hPhysicalGpu = ...
  NvAPI_Status nv_status = NVAPI_OK;
  // 現在のGPU使用率の取得
  NvU32 act_pct = 0;
  NV_GPU_DYNAMIC_PSTATES_INFO_EX info = {0,};
  info.version = NV_GPU_DYNAMIC_PSTATES_INFO_EX_VER;
  nv_status = NvAPI_GPU_GetDynamicPstatesInfoEx( m_handle, &info );
  if ( nv_status == NVAPI_OK ) {
    // ドキュメントにはutilization[NVAPI_GPU_UTILIZATION_DOMAIN_GPU]で
    // 参照できると書いてあるが、ヘッダにはNVAPI_GPU_UTILIZATION_DOMAIN_GPUの
    // 定義が見当たらない。
    // おそらく GPU FB VID BUS と並んでいるので0番の要素を参照する。
    if ( info.utilization[0].bIsPresent > 0 ) {
      // 単位は[%]
      act_pct = info.utilization[0].percentage;
    }
  }

コアクロックの取得
  // 物理GPUハンドルは取得済みであるものとする
  NvPhysicalGpuHandle hPhysicalGpu = ...
  NvAPI_Status nv_status = NVAPI_OK;
  // 最大クロックの取得
  NvU32 max_clock = 0;
  NV_GPU_CLOCK_FREQUENCIES freqs = {0,};
  freqs.version = NV_GPU_CLOCK_FREQUENCIES_VER;
  freqs.ClockType = NV_GPU_CLOCK_FREQUENCIES_BOOST_CLOCK;
  nv_status = NvAPI_GPU_GetAllClockFrequencies( hPhysicalGpu, &freqs );
  if ( nv_status == NVAPI_OK ) {
    if ( freqs.domain[NVAPI_GPU_PUBLIC_CLOCK_GRAPHICS].bIsPresent > 0 ) {
      // 単位はkHz
      max_clock = freqs.domain[NVAPI_GPU_PUBLIC_CLOCK_GRAPHICS].frequency;
    }
  }
  // 現在のクロックの取得
  NvS32 cur_clock = 0;
  // ここではfreqs構造体を使いまわしている
  // 現在のクロックを取得する場合はClockTypeをNV_GPU_CLOCK_FREQUENCIES_CURRENT_FREQにする
  freqs.ClockType = NV_GPU_CLOCK_FREQUENCIES_CURRENT_FREQ;
  nv_status = NvAPI_GPU_GetAllClockFrequencies( hPhysicalGpu, &freqs );
  if ( nv_status == NVAPI_OK ) {
    if ( freqs.domain[NVAPI_GPU_PUBLIC_CLOCK_GRAPHICS].bIsPresent > 0 ) {
      cur_clock = freqs.domain[NVAPI_GPU_PUBLIC_CLOCK_GRAPHICS].frequency;
    }
  }

GPUファン速度の取得
※GPUモデルによっては取得できない場合がある
  // 物理GPUハンドルは取得済みであるものとする
  NvPhysicalGpuHandle hPhysicalGpu = ...
  NvAPI_Status nv_status = NVAPI_OK;
  // 最大回転数の取得
  NvU32 cur_rpm = 0;
  nv_status = NvAPI_GPU_GetTachReading( hPhysicalGpu , &cur_rpm );
  if ( nv_status == NVAPI_OK ) {
    // OK
  }

0 件のコメント:

コメントを投稿