キャッシュの情報を調べる方法
2021/05/10
#linux #hpc

最近趣味や講義などで高性能計算に触れています。コンピューターの性能を最大限引き出して計算をさせるためにはキャッシュをうまく使うことが非常に重要です。例えば行列積の計算ではデータアクセスの順序を変えるとキャッシュヒット率が向上し、計算が数倍早くなります。また、キャッシュブロッキングという方法を用いるとさらに計算が早くなります。

こういったキャッシュを最大限利用した計算をするためにはキャッシュの大きさ、キャッシュラインの大きさなどを事前に知っておくことが必要です。ここではそれらを調べる方法を紹介します。

/sys/devices/system/cpu/cpu*/cache/index*

/sys/devices/system/cpu/cpu*/cache/index*を見るとキャッシュの情報を見ることができます。ここで*にはCPU番号とL1, L2, L3キャッシュのどれかを表す数字が入ります。

例えばCPU0のL1キャッシュの情報は/sys/devices/system/cpu/cpu0/cache/index1に格納されています(私の環境ではindex0も存在したのですが、中身はindex1に入っているものと同一でした)。

lsをしてみると以下のようなファイルがあります。

❯ ls /sys/devices/system/cpu/cpu0/cache/index1
coherency_line_size  level           physical_line_partition  shared_cpu_map  type    ways_of_associativity
id                   number_of_sets  shared_cpu_list          size            uevent

それぞれのファイルがキャッシュの情報を表す数値や文字列を格納しています。Linux Kernel Documentationを見ると以下のように対応しているようです。

Name Description
coherency_line_size キャッシュラインの大きさ[B]
level L1, L2, L3, L4, ...キャッシュのどれか
number_of_sets Set Associative Cacheにおけるsetの数
physical_line_partition number of physical cache line per cache tag(?)
shared_cpu_map キャッシュが共有されているCPUのリストを表すマスク
shared_cpu_list キャッシュが共有されているCPUのリスト
size キャッシュサイズ[KB]
type キャッシュの種類
ways_of_associativity Set Associative Cacheにおけるwayの数
write_policy キャッシュへの書き込み方法の種類(自分の環境では存在しませんでした)

例えばCPU0のL1キャッシュのキャッシュラインの大きさを調べるには以下のようにします。

❯ cat /sys/devices/system/cpu/cpu0/cache/index1/coherency_line_size
64

表にある通り、Set数や何Wayあるかといった情報も調べることができます。この方法がこのページで紹介しているものだと最も詳しくキャッシュの情報を調べることができます。

getconf

getconfを利用するとキャッシュの大きさ, キャッシュラインの大きさ, wayの数などの情報を表示することができます。

❯ getconf -a | grep CACHE
LEVEL1_ICACHE_SIZE                 32768
LEVEL1_ICACHE_ASSOC                8
LEVEL1_ICACHE_LINESIZE             64
LEVEL1_DCACHE_SIZE                 32768
LEVEL1_DCACHE_ASSOC                8
LEVEL1_DCACHE_LINESIZE             64
LEVEL2_CACHE_SIZE                  524288
LEVEL2_CACHE_ASSOC                 8
LEVEL2_CACHE_LINESIZE              64
LEVEL3_CACHE_SIZE                  33554432
LEVEL3_CACHE_ASSOC                 0
LEVEL3_CACHE_LINESIZE              64
LEVEL4_CACHE_SIZE                  0
LEVEL4_CACHE_ASSOC                 0
LEVEL4_CACHE_LINESIZE              0

LEVEL1_ICACHEはL1命令キャッシュ, LEVEL1_DCACHEはL1データキャッシュ, LEVEL2_CACHEはL2キャッシュに対応します。残りも同様です。

それぞれSIZE, ASSOC, LINESIZEでキャッシュの大きさ、wayの数、キャッシュラインの大きさを表しています。サイズの大きさの単位はByteです。

この例だとL1データキャッシュは32KBの大きさを持ち、キャッシュラインの大きさは64Byte, way数は8であることが分かります。

ここでLEVEL3_CACHE_SIZEは32MBとなっていますが、この値は上で見た/sysを調べる方法や、後ほど紹介するlscpuによる方法の2倍になっていることが分かりました。バグなのか分かりませんがこの値を利用する際は注意したほうが良さそうです。

lscpu

lscpuを利用するとキャッシュの大きさを調べることができます。

❯ lscpu
Architecture:                    x86_64
CPU op-mode(s):                  32-bit, 64-bit
Byte Order:                      Little Endian
Address sizes:                   48 bits physical, 48 bits virtual
CPU(s):                          16
On-line CPU(s) list:             0-15
Thread(s) per core:              2
Core(s) per socket:              8
Socket(s):                       1
Vendor ID:                       AuthenticAMD
CPU family:                      23
Model:                           113
Model name:                      AMD Ryzen 7 3700X 8-Core Processor
Stepping:                        0
CPU MHz:                         3600.014
BogoMIPS:                        7200.02
Hypervisor vendor:               Microsoft
Virtualization type:             full
L1d cache:                       256 KiB
L1i cache:                       256 KiB
L2 cache:                        4 MiB
L3 cache:                        16 MiB
Vulnerability Itlb multihit:     Not affected
Vulnerability L1tf:              Not affected
Vulnerability Mds:               Not affected
Vulnerability Meltdown:          Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp
Vulnerability Spectre v1:        Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:        Mitigation; Full AMD retpoline, IBPB conditional, STIBP conditional, RSB filling
Vulnerability Srbds:             Not affected
Vulnerability Tsx async abort:   Not affected
Flags:                           fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr
                                  sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm rep_good nopl cpuid extd_apici
                                 d pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hype
                                 rvisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext ss
                                 bd ibpb stibp vmmcall fsgsbase bmi1 avx2 smep bmi2 rdseed adx smap clflushopt clwb sha_n
                                 i xsaveopt xsavec xgetbv1 xsaves clzero xsaveerptr virt_ssbd arat umip rdpid

L1d cacheからL3 cacheまでの部分にキャッシュの大きさが表示されています。L1が2つあるのはそれぞれ命令用キャッシュとデータ用キャッシュです。ここで表示されているキャッシュの大きさは各CPUコアごとの大きさではなく、全体の大きさであることに注意します。

キャッシュの大きさを調べるだけならこの方法が最も簡単だと思います。

参考文献