Last active
January 30, 2026 10:01
-
-
Save nandhu-44/fe9bf4c512cfd158a8d09e9cc22021ee to your computer and use it in GitHub Desktop.
List specs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Tejaswi HPC Node Hardware Specs Collector | |
| Lists detailed CPU and GPU information for the current node. | |
| Run this script as a regular user (or with sudo for more details like dmidecode). | |
| """ | |
| import subprocess | |
| import sys | |
| from datetime import datetime | |
| def run_command(cmd, check=True, capture_output=True, text=True): | |
| """Helper to run shell commands safely.""" | |
| try: | |
| result = subprocess.run( | |
| cmd, shell=True, check=check, | |
| capture_output=capture_output, text=text | |
| ) | |
| return result.stdout.strip() if capture_output else result | |
| except subprocess.CalledProcessError as e: | |
| print(f"Command failed: {cmd}\nError: {e.stderr.strip()}", file=sys.stderr) | |
| return None | |
| def get_cpu_info(): | |
| """Gather and print detailed CPU information — nothing omitted.""" | |
| info = {} | |
| # lscpu full output parsed | |
| lscpu = run_command("lscpu") | |
| if lscpu: | |
| for line in lscpu.splitlines(): | |
| if ':' in line: | |
| key, val = line.split(':', 1) | |
| info[key.strip()] = val.strip() | |
| # Model name from /proc/cpuinfo | |
| model = run_command("cat /proc/cpuinfo | grep 'model name' | head -1 | cut -d':' -f2-") | |
| if model: | |
| info["Model Name"] = model.strip() | |
| sockets = info.get("Socket(s)", "N/A") | |
| cores_per_socket = info.get("Core(s) per socket", "N/A") | |
| threads_per_core = info.get("Thread(s) per core", "N/A") | |
| total_cpus = info.get("CPU(s)", "N/A") | |
| print("\n=== CPU / Processor Summary (full details) ===") | |
| print(f"Architecture: {info.get('Architecture', 'N/A')}") | |
| print(f"Model Name: {info.get('Model Name', 'N/A')}") | |
| print(f"CPU op-mode(s): {info.get('CPU op-mode(s)', 'N/A')}") | |
| print(f"Byte Order: {info.get('Byte Order', 'N/A')}") | |
| print(f"Address sizes: {info.get('Address sizes', 'N/A')}") | |
| print(f"CPU(s): {total_cpus}") | |
| print(f"On-line CPU(s) list: {info.get('On-line CPU(s) list', 'N/A')}") | |
| print(f"Thread(s) per core: {threads_per_core}") | |
| print(f"Core(s) per socket: {cores_per_socket}") | |
| print(f"Socket(s): {sockets}") | |
| print(f"NUMA node(s): {info.get('NUMA node(s)', 'N/A')}") | |
| print(f"Vendor ID: {info.get('Vendor ID', 'N/A')}") | |
| print(f"CPU family: {info.get('CPU family', 'N/A')}") | |
| print(f"Model: {info.get('Model', 'N/A')}") | |
| print(f"Model name: {info.get('Model name', 'N/A')}") | |
| print(f"Stepping: {info.get('Stepping', 'N/A')}") | |
| print(f"CPU MHz: {info.get('CPU MHz', 'N/A')}") | |
| print(f"CPU max MHz: {info.get('CPU max MHz', 'N/A')}") | |
| print(f"CPU min MHz: {info.get('CPU min MHz', 'N/A')}") | |
| print(f"BogoMIPS: {info.get('BogoMIPS', 'N/A')}") | |
| print(f"Virtualization: {info.get('Virtualization', 'N/A')}") | |
| print(f"L1d cache: {info.get('L1d cache', 'N/A')}") | |
| print(f"L1i cache: {info.get('L1i cache', 'N/A')}") | |
| print(f"L2 cache: {info.get('L2 cache', 'N/A')}") | |
| print(f"L3 cache: {info.get('L3 cache', 'N/A')}") | |
| print(f"NUMA node0 CPU(s): {info.get('NUMA node0 CPU(s)', 'N/A')}") | |
| # Print ALL NUMA mappings fully — no omission | |
| print("\nFull NUMA Node → CPU Mappings:") | |
| numa_lines = run_command("lscpu | grep 'NUMA node.*CPU(s)'") | |
| if numa_lines: | |
| for line in numa_lines.splitlines(): | |
| if line.strip(): | |
| print(" " + line.strip()) | |
| else: | |
| print(" (No NUMA mapping details found)") | |
| def get_gpu_info(): | |
| """Gather NVIDIA GPU information using nvidia-smi.""" | |
| print("\n=== GPU Summary (via nvidia-smi) ===") | |
| smi_summary = run_command("nvidia-smi --query-gpu=index,name,memory.total,memory.used,utilization.gpu,power.draw,power.limit,temperature.gpu --format=csv,noheader,nounits") | |
| if not smi_summary: | |
| print("nvidia-smi not found or failed.") | |
| return | |
| print("GPU | Name | Mem Total/Used (MiB) | Util (%) | Power (W) | Temp (°C)") | |
| print("-" * 85) | |
| for line in smi_summary.splitlines(): | |
| fields = [f.strip() for f in line.split(',')] | |
| if len(fields) >= 7: | |
| idx, name, mem_total, mem_used, util, pwr, temp = fields[0], fields[1], fields[2], fields[3], fields[4], fields[5], fields[6] | |
| pwr_limit = fields[6] if len(fields) > 6 else "N/A" | |
| print(f"{idx:>3} | {name:<21} | {mem_total:>6} / {mem_used:>6} | {util:>7} | {pwr:>4}/{pwr_limit:>4} | {temp:>4}") | |
| # Driver & CUDA | |
| driver_line = run_command("nvidia-smi | head -n 1 | grep -o 'Driver Version:.*CUDA Version:.*'") | |
| if driver_line: | |
| print(f"\n{driver_line}") | |
| # Topology | |
| topo = run_command("nvidia-smi topo -m") | |
| if topo: | |
| print("\nGPU Interconnect Topology (full):") | |
| print(topo) | |
| def main(): | |
| print(f"Tejaswi HPC Node Hardware Specs Report") | |
| print(f"Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S IST')}") | |
| print(f"Hostname: {run_command('hostname -f') or 'N/A'}") | |
| print("=" * 70) | |
| get_cpu_info() | |
| get_gpu_info() | |
| print("\nNote: For even more hardware details (DIMM layout, BIOS, etc.), run with sudo:") | |
| print(" sudo dmidecode --type memory | grep -E 'Size|Locator|Speed|Manufacturer|Part'") | |
| print(" sudo dmidecode --type processor | grep -E 'Version|Core|Thread|Family| stepping'") | |
| print("\nDone. This shows specs of THIS node only.") | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment