Linux上,CPU和Cache相关的拓扑结构,都可以从sysfs文件系统的目录 /sys/devices/system/cpu/ 来获取详细信息。
在网上,找了对CPU相关拓扑结构的解析的两个脚本,觉得还不错;尽管看起来仍有些粗糙,也暂时去改进了。
一个是来自:https://gist.github.com/stedolan/1089968 ; 它可以打印出每个逻辑CPU属于那儿Socket、哪个core,以及与哪些CPU共享L1/L2/L3的Cache。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#!/bin/bash unshared () { grep '^[0-9]\+$' "$1" > /dev/null } for cpu in $(ls -d /sys/devices/system/cpu/cpu[0-9]* | sort -t u -k 3 -n); do echo "${cpu##*/}: [Package #$(cat $cpu/topology/physical_package_id), Core #$(cat $cpu/topology/core_id)]" if ! unshared $cpu/topology/core_siblings_list; then echo " same package as $(cat $cpu/topology/core_siblings_list)" fi if ! unshared $cpu/topology/thread_siblings_list; then echo " same core as $(cat $cpu/topology/thread_siblings_list)" fi for cache in $cpu/cache/index*; do printf " %-15s " "L$(cat $cache/level) $(cat $cache/type):" echo "$(cat $cache/size) $(cat $cache/ways_of_associativity)-way with $(cat $cache/coherency_line_size) byte lines" if ! unshared $cache/shared_cpu_list; then printf " %-15s [%s]\n" "" "shared with $(cat $cache/shared_cpu_list)" fi done echo done |
另一个时候cpu_layout.py脚本,来自dpdk项目,用于展示CPU的拓扑结构(不包括cache的信息):http://dpdk.org/browse/dpdk/tree/usertools/cpu_layout.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
#!/usr/bin/env python # # BSD LICENSE (此处省略过多的License信息) from __future__ import print_function import sys try: xrange # Python 2 except NameError: xrange = range # Python 3 sockets = [] cores = [] core_map = {} base_path = "/sys/devices/system/cpu" fd = open("{}/kernel_max".format(base_path)) max_cpus = int(fd.read()) fd.close() for cpu in xrange(max_cpus + 1): try: fd = open("{}/cpu{}/topology/core_id".format(base_path, cpu)) except IOError: continue except: break core = int(fd.read()) fd.close() fd = open("{}/cpu{}/topology/physical_package_id".format(base_path, cpu)) socket = int(fd.read()) fd.close() if core not in cores: cores.append(core) if socket not in sockets: sockets.append(socket) key = (socket, core) if key not in core_map: core_map[key] = [] core_map[key].append(cpu) print(format("=" * (47 + len(base_path)))) print("Core and Socket Information (as reported by '{}')".format(base_path)) print("{}\n".format("=" * (47 + len(base_path)))) print("cores = ", cores) print("sockets = ", sockets) print("") max_processor_len = len(str(len(cores) * len(sockets) * 2 - 1)) max_thread_count = len(list(core_map.values())[0]) max_core_map_len = (max_processor_len * max_thread_count) \ + len(", ") * (max_thread_count - 1) \ + len('[]') + len('Socket ') max_core_id_len = len(str(max(cores))) output = " ".ljust(max_core_id_len + len('Core ')) for s in sockets: output += " Socket %s" % str(s).ljust(max_core_map_len - len('Socket ')) print(output) output = " ".ljust(max_core_id_len + len('Core ')) for s in sockets: output += " --------".ljust(max_core_map_len) output += " " print(output) for c in cores: output = "Core %s" % str(c).ljust(max_core_id_len) for s in sockets: if (s,c) in core_map: output += " " + str(core_map[(s, c)]).ljust(max_core_map_len) else: output += " " * (max_core_map_len + 1) print(output) |
当NUMA架构下,你可能还需要了解NUMA的分布,包括每个节点上有哪些逻辑处理器、有多少内存等信息,那么使用numactl工具来查看(在CentOS上可以用yum install numactl命令来安装该工具)。
1 2 3 4 5 6 7 8 9 10 11 12 |
[root@jay-linux ~]$ numactl --hardware available: 2 nodes (0-1) node 0 cpus: 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23 node 0 size: 64395 MB node 0 free: 62846 MB node 1 cpus: 8 9 10 11 12 13 14 15 24 25 26 27 28 29 30 31 node 1 size: 64507 MB node 1 free: 63676 MB node distances: node 0 1 0: 10 20 1: 20 10 |
另外,lscpu 命令也是可以查看很多CPU的信息(包括:架构、逻辑CPU数量、核数、主频、Cache大小、NUMA信息等),该命令在CentOS上是在 util-linux 软件包中。