WindowsのPythonでCPUの拡張命令セットを確認する

## はじめに

TensorFlowをソースからコンパイルする時などに、CPUの拡張命令セットを知りたいことがあります。
Linuxであれば、/proc/cpuinfoで確認できます。
Windowsで取得する方法を探していたらPythonで出来る方法を見つけました。


## 環境

- OS     : Windows 10
- Python : Python 3.7.7
- cpuid  : 0.0.9


## 必要なモジュールのインスト―ル

Pythonの cpuid モジュールをインストールします。

```shell
>pip install cpuid
```


# コード

実行するコードは下記になります。
cpuid_chk.py として、保存します。

```python:cpuid_chk.py
import cpuid

print("Vendor ID         : %s" % cpuid.cpu_vendor())
print("CPU name          : %s" % cpuid.cpu_name())
print("Microarchitecture : %s%s" % cpuid.cpu_microarchitecture())
print("Vector instructions supported:")
print("SSE       : %s" % cpuid._is_set(1, 3, 25))
print("SSE2      : %s" % cpuid._is_set(1, 3, 26))
print("SSE3      : %s" % cpuid._is_set(1, 2, 0))
print("SSSE3     : %s" % cpuid._is_set(1, 2, 9))
print("SSE4.1    : %s" % cpuid._is_set(1, 2, 19))
print("SSE4.2    : %s" % cpuid._is_set(1, 2, 20))
print("SSE4a     : %s" % cpuid._is_set(0x80000001, 2, 6))
print("AVX       : %s" % cpuid._is_set(1, 2, 28))
print("AVX2      : %s" % cpuid._is_set(7, 1, 5))
print("BMI1      : %s" % cpuid._is_set(7, 1, 3))
print("BMI2      : %s" % cpuid._is_set(7, 1, 8))
```


## 実行結果

cpuid_chk.py を実行すると、下記の結果が得られます。

```shell
>python cpuid_chk.py
Vendor ID         : GenuineIntel
CPU name          : Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
Microarchitecture : kabylake
Vector instructions supported:
SSE       : Yes
SSE2      : Yes
SSE3      : Yes
SSSE3     : Yes
SSE4.1    : Yes
SSE4.2    : Yes
SSE4a     : --
AVX       : Yes
AVX2      : Yes
BMI1      : Yes
BMI2      : Yes
```

SSE4.2、AVX2、BMI2 に対応していることがわかります。


## この記事のコードについて

この記事のコードは、cpuid のソースを元にしています。
その際の経緯を以下に記述します。

まずはcpuid のソースコードの場所を確認します。

```shell
>pip show cpuid
```

「Location:」にcpuidのインストールパスが書かれています。
そのディレクトリの中にソース（cpuid.py）があります。

ソースの370行目に、下記のような記述があります。

```python:cpuid.py
if __name__ == "__main__":
    
    print("Vendor ID         : %s" % cpu_vendor())
    print("CPU name          : %s" % cpu_name())
    print("Microarchitecture : %s%s" % cpu_microarchitecture())
    print("Vector instructions supported:")
    print("SSE       : %s" % is_set(1, 3, 25))
    print("SSE2      : %s" % is_set(1, 3, 26))
    print("SSE3      : %s" % is_set(1, 2, 0))
    print("SSSE3     : %s" % is_set(1, 2, 9))
    print("SSE4.1    : %s" % is_set(1, 2, 19))
    print("SSE4.2    : %s" % is_set(1, 2, 20))
    print("SSE4a     : %s" % is_set(0x80000001, 2, 6))
    print("AVX       : %s" % is_set(1, 2, 28))
    print("AVX2      : %s" % is_set(7, 1, 5))
    print("BMI1      : %s" % is_set(7, 1, 3))
    print("BMI2      : %s" % is_set(7, 1, 8))
```

直接、cpuid.pyを実行すればCPUの情報が得られそうですが、
実際に実行すると、下記のエラーが表示されます。

```shell
>cd [cpuidのインストールパス]
>python cpuid.py
Vendor ID         : GenuineIntel
CPU name          : Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
Microarchitecture : kabylake
Vector instructions supported:
Traceback (most recent call last):
  File "cpuid.py", line 376, in <module>
    print("SSE       : %s" % is_set(1, 3, 25))
NameError: name 'is_set' is not defined
```

呼び出している関数は、「is_set」なのに、
ソース内で定義されている関数は、「_is_set」です。
そのため、not defined となっています。

cpuidモジュールをimportして、「_is_set」を呼び出すようにしたのが、この記事のコードです。

## 「error: Microsoft Visual C++ 14.0 is required」の対処

pip install を実行したときに、下記のエラーが出ることがあります。
解決のために「Visual C++ Build Tools 」をインストールします。

```
error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": https://visualstudio.microsoft.com/downloads/
```

[https://visualstudio.microsoft.com/ja/downloads/](https://visualstudio.microsoft.com/ja/downloads/)からダウンロードします。

「すべてのダウンロード」から
「Visual Studio 2019のツール」をクリックして展開します。
「Build Tools for Visual Studio 2019」の右側の「ダウンロード」をクリックしてダウンロードを開始します。

ダウンロードした
「vs_buildtools_1861876476.1586696342.exe」
をダブルクリックして、インストールします。

インストールが終わると「Visual Studio Installer」が起動します。
※スタートメニューにも登録されているので、そちらからも起動できます。

「C++ Build Tools」にチェックを入れます。
「インストール」ボタンをクリックする。

Windowsの再起動を要求されたので、実施します。

これで、pip が実行できます。


## 最後に

WindowsでCPUの拡張命令セットの確認が楽になりました。
TensorFlowのコンパイルが失敗して、インストールが失敗するのは別の話・・・。
先は長いです。