From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 6BDB0457C0; Wed, 14 Aug 2024 13:19:30 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4B56742E72; Wed, 14 Aug 2024 13:19:26 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.12]) by mails.dpdk.org (Postfix) with ESMTP id CD22F40274 for ; Wed, 14 Aug 2024 13:19:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1723634364; x=1755170364; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qpcQGj/qJ9IbjUSOOOd9zJ6SqWg6hI+s0kPAeyzF5Kk=; b=ZERI1R750wJ/MSNQR3iMN/BB9/TQei9RjUzoyoJQOOg3jQpBO7PXZvFz rycA+Ra3m3Y96WyEC3cmFwnnYKP3d4ReIKJiNWi8emvcEI2gTHFf5xXEm m9LoBIJv+HX5pQ/RgkWTsarobHCcUk3YeMBpazTGJKcsvJpd2GqHxbgJW /xVGS2ffO2AKk5E8pnEZXntA/f9LK35KLRxEJHIxSkga6iMTeh3OSX/Lw bH6vErzGaYk7ewHwXd4iu6VqcTurpJpHSOsV+RTf8w63ukCbKhFEXJCTj QGqIHA7ByLkpMuZYXqGc0ELvZZ/2LgewdU5TBbUXkjt1Hu7zDcILyRSqr g==; X-CSE-ConnectionGUID: bCcONf12SAae/LTv5VtrGA== X-CSE-MsgGUID: jiH6Ti86RIKGuSPw6nAAIw== X-IronPort-AV: E=McAfee;i="6700,10204,11163"; a="25705957" X-IronPort-AV: E=Sophos;i="6.09,145,1716274800"; d="scan'208";a="25705957" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by fmvoesa106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Aug 2024 04:19:23 -0700 X-CSE-ConnectionGUID: yYvf++VKQRCl+7Nd5vfbrA== X-CSE-MsgGUID: c7em5ntfRliF1E2BfIa94Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.09,145,1716274800"; d="scan'208";a="59554298" Received: from silpixa00401119.ir.intel.com ([10.55.129.167]) by orviesa007.jf.intel.com with ESMTP; 14 Aug 2024 04:19:22 -0700 From: Anatoly Burakov To: dev@dpdk.org, Robin Jarry Cc: bruce.richardson@intel.com Subject: [PATCH v1 2/2] usertools/cpu_layout: print out NUMA nodes Date: Wed, 14 Aug 2024 12:19:19 +0100 Message-ID: X-Mailer: git-send-email 2.43.5 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org In traditional NUMA case, NUMA nodes and physical sockets were used interchangeably, but there are cases where there can be multiple NUMA nodes per socket, as well as all CPU's being assigned NUMA node 0 even in cases of multiple sockets. Use sysfs to print out NUMA information. Signed-off-by: Anatoly Burakov --- usertools/cpu_layout.py | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/usertools/cpu_layout.py b/usertools/cpu_layout.py index 843b29a134..be89909464 100755 --- a/usertools/cpu_layout.py +++ b/usertools/cpu_layout.py @@ -4,6 +4,7 @@ # Copyright(c) 2017 Cavium, Inc. All rights reserved. from typing import List, Set, Dict, Tuple +import glob def _range_expand(rstr: str) -> List[int]: @@ -26,11 +27,19 @@ def _read_sysfs(path: str) -> str: return fd.read().strip() +def _read_numa_node(base: str) -> int: + node_glob = f"{base}/node*" + node_dirs = glob.glob(node_glob) + if not node_dirs: + return 0 # default to node 0 + return int(node_dirs[0].split("node")[1]) + + def _print_row(row: Tuple[str, ...], col_widths: List[int]) -> None: first, *rest = row w_first, *w_rest = col_widths first_end = " " * 4 - rest_end = " " * 10 + rest_end = " " * 4 print(first.ljust(w_first), end=first_end) for cell, width in zip(rest, w_rest): @@ -50,6 +59,7 @@ def _main() -> None: sockets_s: Set[int] = set() cores_s: Set[int] = set() core_map: Dict[Tuple[int, int], List[int]] = {} + numa_map: Dict[int, int] = {} base_path = "/sys/devices/system/cpu" cpus = _range_expand(_read_sysfs(f"{base_path}/online")) @@ -58,12 +68,14 @@ def _main() -> None: lcore_base = f"{base_path}/cpu{cpu}" core = int(_read_sysfs(f"{lcore_base}/topology/core_id")) socket = int(_read_sysfs(f"{lcore_base}/topology/physical_package_id")) + node = _read_numa_node(lcore_base) cores_s.add(core) sockets_s.add(socket) key = (socket, core) core_map.setdefault(key, []) core_map[key].append(cpu) + numa_map[cpu] = node cores = sorted(cores_s) sockets = sorted(sockets_s) @@ -73,24 +85,37 @@ def _main() -> None: print("cores = ", cores) print("sockets = ", sockets) + print("numa = ", sorted(set(numa_map.values()))) print() - # Core, [Socket, Socket, ...] - heading_strs = "", *[f"Socket {s}" for s in sockets] + # Core, [NUMA, Socket, NUMA, Socket, ...] + heading_strs = "", *[v for s in sockets for v in ("", f"Socket {s}")] sep_strs = tuple("-" * len(hstr) for hstr in heading_strs) rows: List[Tuple[str, ...]] = [] + prev_numa = None for c in cores: # Core, row: Tuple[str, ...] = (f"Core {c}",) - # [lcores, lcores, ...] + # assume NUMA changes symmetrically + first_lcore = core_map[(0, c)][0] + cur_numa = numa_map[first_lcore] + numa_changed = prev_numa != cur_numa + prev_numa = cur_numa + + # [NUMA, lcores, NUMA, lcores, ...] for s in sockets: try: lcores = core_map[(s, c)] + numa = numa_map[lcores[0]] + if numa_changed: + row += (f"NUMA {numa}",) + else: + row += ("",) row += (f"{lcores}",) except KeyError: - row += ("",) + row += ("", "") rows += [row] # find max widths for each column, including header and rows -- 2.43.5