QSVEncのお手軽CPU/GPU世代判別
QSVEnc 2.06では、IvyBridge系統のGPUではピラミッド参照をオフにする、という機能を追加した。
このためにはCPU(GPU)の世代判別を行わないといけないのだけど、その方法はわりとお手軽に行っている。
※2015.08.13 Skylakeの判別について追記。
QSVがサポートされるGPUの世代
Skylake世代
Broadwell世代
Haswell世代
IvyBridge世代
SandyBridge世代
これらを見分けたい。
IntelのGPUはCPUとセットなので、CPUの世代がわかればGPUの世代もわかる。
一番簡単には、例えばAVX2サポートならHaswell以降、などとする方法がある。ただ、これは残念ながら不確実で、HaswellなPentiumなどではAVX2はサポートされないし、ついでにBMI/BMI2/FMA3/AES/F16C命令もサポートされない。
他にはcpuidのモデルナンバーとかを見る方法がある。ただ、これはHaswellだけでいろいろなモデルナンバーがあるので、それをいちいちコードに列挙するのはめちゃくちゃめんどくさい。なのでやはり対応命令のチェックなどでなんとかしたい。
最近のIntel CPUは世代ごとに新たな命令が追加されていてAVX/AVX2以外にもいろいろな謎の命令が追加されている。
そこで、例えばこのあたりとにらめっこすると、いまのところ以下のように判定することができることがわかる。
判定スタート (対応していれば、右矢印へ)
↓
MPX命令 → Skylake
↓
RDSEED命令 → Broadwell
↓
MOVBE命令 + FSGSBASE命令 → Haswell
↓
QSVのICQモード → Airmont (Braswell) (= GPUはHaswell世代)
↓
FSGSBASE命令 → IvyBridge
↓
RDRAND命令 → Silvermont (= GPUはIvy世代)
↓
SandyBridge
まあ、何に使うのかよくわからん謎な命令たちだが、これらのサポートフラグをcpuidでチェックするだけで、お手軽に判定できることがわかる。
QSVEncでは、上の方法をそのままコードにしてある。
きっとちゃんと判定できているはず。(Core2とかAMDとかでやるとどうなるの、とか細かいことは気にしない。なんせQSVがないので関係ない)
もっと簡単な方法あるかなあ…。
このためにはCPU(GPU)の世代判別を行わないといけないのだけど、その方法はわりとお手軽に行っている。
※2015.08.13 Skylakeの判別について追記。
QSVがサポートされるGPUの世代
Skylake世代
Broadwell世代
Haswell世代
IvyBridge世代
SandyBridge世代
これらを見分けたい。
IntelのGPUはCPUとセットなので、CPUの世代がわかればGPUの世代もわかる。
一番簡単には、例えばAVX2サポートならHaswell以降、などとする方法がある。ただ、これは残念ながら不確実で、HaswellなPentiumなどではAVX2はサポートされないし、ついでにBMI/BMI2/FMA3/AES/F16C命令もサポートされない。
他にはcpuidのモデルナンバーとかを見る方法がある。ただ、これはHaswellだけでいろいろなモデルナンバーがあるので、それをいちいちコードに列挙するのはめちゃくちゃめんどくさい。なのでやはり対応命令のチェックなどでなんとかしたい。
最近のIntel CPUは世代ごとに新たな命令が追加されていてAVX/AVX2以外にもいろいろな謎の命令が追加されている。
そこで、例えばこのあたりとにらめっこすると、いまのところ以下のように判定することができることがわかる。
判定スタート (対応していれば、右矢印へ)
↓
MPX命令 → Skylake
↓
RDSEED命令 → Broadwell
↓
MOVBE命令 + FSGSBASE命令 → Haswell
↓
QSVのICQモード → Airmont (Braswell) (= GPUはHaswell世代)
↓
FSGSBASE命令 → IvyBridge
↓
RDRAND命令 → Silvermont (= GPUはIvy世代)
↓
SandyBridge
まあ、何に使うのかよくわからん謎な命令たちだが、これらのサポートフラグをcpuidでチェックするだけで、お手軽に判定できることがわかる。
QSVEncでは、上の方法をそのままコードにしてある。
#include <intrin.h>
int getCPUGen() {
int CPUInfo[4];
__cpuid(CPUInfo, 0x01);
bool bMOVBE = !!(CPUInfo[2] & (1<<22));
bool bRDRand = !!(CPUInfo[2] & (1<<30));
__cpuid(CPUInfo, 0x07);
bool bMPX = !!(CPUInfo[1] & (1<<14));
bool bRDSeed = !!(CPUInfo[1] & (1<<17));
bool bFsgsbase = !!(CPUInfo[1] & (1));
if (bMPX) return CPU_GEN_SKYLAKE;
if (bRDSeed) return CPU_GEN_BROADWELL;
if (bMOVBE && bFsgsbase) return CPU_GEN_HASWELL;
//ICQのサポートをチェックする
bool bICQ = !!(CheckEncodeFeature(true, get_mfx_libhw_version(), MFX_RATECONTROL_ICQ, MFX_CODEC_AVC) & ENC_FEATURE_CURRENT_RC);
if (bICQ) return CPU_GEN_AIRMONT;
if (bFsgsbase) return CPU_GEN_IVYBRIDGE;
if (bRDRand) return CPU_GEN_SILVERMONT;
return CPU_GEN_SANDYBRIDGE;
}
きっとちゃんと判定できているはず。(Core2とかAMDとかでやるとどうなるの、とか細かいことは気にしない。なんせQSVがないので関係ない)
もっと簡単な方法あるかなあ…。
スポンサーサイト