Naveen Kumar Mishra
Naveen Kumar Mishra

Reputation: 351

How to get the size of the CPU cache in Linux

I have executed the following query:

free -m

And output of this command is:

           total       used       free     shared    buffers     cached
Mem:        2048       2018         29          5          0       595

I want to get the size of the CPU cache. Is it possible to get the size of the cache and also what is the use of the cache here?

Upvotes: 18

Views: 29281

Answers (5)

vinc17
vinc17

Reputation: 3476

First, there are several kinds/levels of caches, e.g. level 1 data, level 1 instruction, level 2, and level 3. In short, L3 cache is generally completely shared, and the other ones may be partly shared (e.g. L1 cache being private to each physical cores, but shared between the associated virtual cores when hyper-threading is used).

I'm going to complete myaut's answer (the lscpu utility giving the total cache sizes for each kind of caches, /sys/devices/system/cpu/cpu*/cache/index* giving per-cpu details). If you want to see the size of each individual cache and how the caches are shared, the best utility to my knownledge is lstopo (for X11) or lstopo-no-graphics (text output) from the hwloc project. The cpu-x utility also gives information about the CPU caches.

For the per-cpu sizes, I use the following zsh script:

#!/usr/bin/env zsh
setopt EXTENDED_GLOB
for i in /sys/devices/system/cpu/cpu[0-9]#(n)
do
  c=()
  for j in $i/cache/index*
  do
    c+=("$(<$j/size) $(<$j/type)")
  done
  printf "%-6s %s\n" $i:t "${(j: / :)c}"
done

For instance, on my laptop, I get:

cpu0   48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu1   48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu2   48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu3   48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu4   48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu5   48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu6   48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu7   48K Data / 32K Instruction / 1280K Unified / 18432K Unified
cpu8   32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu9   32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu10  32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu11  32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu12  32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu13  32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu14  32K Data / 64K Instruction / 2048K Unified / 18432K Unified
cpu15  32K Data / 64K Instruction / 2048K Unified / 18432K Unified

Note that getconf outputs non-deterministic values on heterogeneous x86 like the above one (at least with glibc 2.40). Do not use it on such a system.

Upvotes: 0

getconf

getconf -a | grep CACHE

gives:

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                  262144
LEVEL2_CACHE_ASSOC                 8
LEVEL2_CACHE_LINESIZE              64
LEVEL3_CACHE_SIZE                  20971520
LEVEL3_CACHE_ASSOC                 20
LEVEL3_CACHE_LINESIZE              64
LEVEL4_CACHE_SIZE                  0
LEVEL4_CACHE_ASSOC                 0
LEVEL4_CACHE_LINESIZE              0

Or for a single level:

getconf LEVEL2_CACHE_SIZE

The cool thing about this interface is that it is just a wrapper around the POSIX sysconf C function (cache arguments are non-POSIX extensions), and so it can be used from C code as well:

long l2 = sysconf(_SC_LEVEL2_CACHE_SIZE);

Tested on Ubuntu 16.04 (Xenial Xerus).

x86 CPUID instruction

The CPUID x86 instruction also offers cache information, and can be directly accessed by userland.

glibc seems to use that method for x86. I haven't confirmed by step debugging / instruction tracing, but the source for 2.28 sysdeps/x86/cacheinfo.c does that:

__cpuid (2, eax, ebx, ecx, edx);

TODO: Create a minimal C example, lazy now, asked at: How to receive L1, L2 & L3 cache size using CPUID instruction in x86

ARM also has an architecture-defined mechanism to find cache sizes through registers such as the Cache Size ID Register (CCSIDR), see the ARMv8 Programmers' Manual 11.6 "Cache discovery" for an overview.

Upvotes: 34

hmmmm
hmmmm

Reputation: 41

For ARM CPUs running Linux (tested on Raspberry Pi 3B+ with Raspbian (32 bit)):

In the "Arm® Cortex®-A53 MPCore Processor Technical Reference Manual" is a chapter, "Cache Size Selection Register" and "Cache Size ID Register", including assembler instructions.

These assembler instructions are already available as functions in the Linux kernel headers asm/cachetype.h: set_csselr(...) and read_ccsidr(), but these function can not be called in user mode, so we need to build a kernel module to get/print the values:

Makefile:

obj-m += cachesize.o

all:

    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:

    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

File cachesize.c:

#include <asm/cachetype.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Abc defg");
MODULE_DESCRIPTION("Find out ARM cache sizes");
MODULE_VERSION("0.01");

static int __init lkm_example_init(void) {
// Must run in kernel mode
// Assumptions: L1 (instructions + data), L2 (check your CPU manual)
 set_csselr(0);
 printk(KERN_INFO "ccsidr L1 data cache = %08x\n", read_ccsidr());
 set_csselr(1);
 printk(KERN_INFO "ccsidr L1 instruction cache = %08x\n", read_ccsidr());
 set_csselr(2);
 printk(KERN_INFO "ccsidr L2 unified = %08x\n", read_ccsidr());
 return 0;
}

static void __exit lkm_example_exit(void) {
 printk(KERN_INFO "Goodbye, World!\n");
}

module_init(lkm_example_init);
module_exit(lkm_example_exit);

then:

make
insmode cachesize.ko
rmmod cachesize
dmesg | tail
# Compare numbers to the table "CCSIDR encodings" in the "ARM ... Technical Reference Manual"

Upvotes: 3

Surajit
Surajit

Reputation: 21

In my virtual machine (Linux dhcppc4 2.6.32-71.el6.i686 #1 SMP Wed Sep 1 01:26:34 EDT 2010 i686 i686 i386 GNU/Linux), I couldn't find /sys/devices/system/node, but lscpu certainly gives the details.

I see some more information in /sys/devices/system/cpu/cpu0/cache/*:

cat /sys/devices/system/cpu/cpu0/cache/index0/size

Output

32K

Upvotes: -1

myaut
myaut

Reputation: 11504

If you want to get the size of the CPU caches in Linux, the easiest way to do that is lscpu:

$ lscpu | grep cache
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              15360K

If you want to get detailed information on each cache, check the sysfs file system:

$ SYSNODE=/sys/devices/system/node
$ grep '.*' $SYSNODE/node*/cpu*/cache/index*/* 2>/dev/null | 
    awk '-F[:/]' '{ printf "%6s %6s %24s %s\n" $6, $7, $9, $10, $11 ; }'
node0  cpu0 index0                    level 1
node0  cpu0 index0           number_of_sets 64
node0  cpu0 index0  physical_line_partition 1
node0  cpu0 index0          shared_cpu_list 0,12
node0  cpu0 index0           shared_cpu_map 0000,00001001
node0  cpu0 index0                     size 32K
node0  cpu0 index0                     type Data
node0  cpu0 index0    ways_of_associativity 8
node0  cpu0 index1      coherency_line_size 64

Some cache instances will be seen multiple times (per each hardware thread), but you can check that in the shared_cpu_list field.

Upvotes: 30

Related Questions