get-available-resources 来源台账解析:资源检测语义的官方依据与版本锚定实践
2026/9/10 23:07:09 网站建设 项目流程

get-available-resources 来源台账解析:资源检测语义的官方依据与版本锚定实践

【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000+ scientists worldwide. 165 ready-to-use validated skills plus 100+ scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills

导读

scientific-agent-skills仓库中的get-available-resources技能,用于在资源敏感型科学计算任务启动前,检测宿主机的 CPU、内存、磁盘、调度器、容器与加速器限额,并输出一份脱敏 JSON 快照。而本技能目录下的skills/get-available-resources/references/sources.md则是一份「官方来源台账」(official-source ledger):它逐条记录了技能中每一项资源语义判断所依据的官方文档、对应版本与查阅日期。本文围绕这份台账展开,说明它如何锚定 psutil、Python 标准库、Linux procfs/cgroup v2、容器与 OCI、NVIDIA、AMD ROCm、Apple、Slurm 与 Windows 等平台的语义结论,并结合仓库内的检测器源码、语义说明文档与测试用例,帮助读者理解「每一个null、每一个not_tested背后都有据可查」这一设计原则。

为什么需要一份「来源台账」

资源检测代码看起来只是读几个系统文件、跑几条管理命令,但其输出会被下游用作并发规划、内存预算与加速器分配的依据。语义稍有偏差——例如把逻辑 CPU 当成物理核、把memory.high当成硬上限、把nvidia-smi的可见性当成 CUDA 运行时可用性——就可能导致进程超订、OOM 甚至错误的调度决策。

references/sources.md的定位是让这些语义判断可追溯、可复核、可更新

  • 每一条语义结论都标注了它依据的官方文档,而不是「凭经验」;
  • 每条来源都附有查阅日期与版本号(如 psutil 7.2.2、Python 3.14.6、OCI Runtime Spec 1.3.0、AMD SMI 7.2.0、ROCm 7.2.4),避免「文档已更新但代码语义未跟上」的漂移;
  • 台账以研究截止日2026-07-23统一锚定,未标注日期的「living docs」也被明确标记。

这与技能主文档skills/get-available-resources/SKILL.md中的要求互相呼应:该文件在「Bundled files」一节明确写道,官方文档于 2026-07-23 刷新,在修改任何语义或依赖锁定之前,必须先查阅references/sources.md。也就是说,这份台账不是可有可无的附录,而是技能语义演进的「变更前必读」文件。

核心约定:盘点 ≠ 可支配

在逐条解读来源之前,需要先理解台账所支撑的总原则。参考skills/get-available-resources/references/resource_semantics.md的「Core rule: inventory is not entitlement」:永远不要把一个主机级计数当作当前进程可用的承诺。可用资源应理解为以下独立观测约束的交集:

  1. 主机盘点(host inventory);
  2. 进程亲和性或处理器组作用域(affinity / processor-group scope);
  3. cgroup/容器约束;
  4. 调度器分配(scheduler allocation);
  5. 加速器可见性与设备权限;
  6. 应用运行时兼容性。

缺失证据意味着unknown,而不是 unlimited。这一条原则正是台账中绝大多数来源条目存在的理由:每个来源都只负责证明六层约束中的某几层,而不是全部。

psutil 与 Python 标准库:进程视角的基础设施

台账将 psutil 与 Python 官方文档归为一组,它们共同支撑「逻辑/物理 CPU、进程亲和性、可用内存、交换与磁盘」的跨平台观测。

psutil 7.2.2

  • 文档用途:区分逻辑 CPU 与物理 CPU 计数;指出系统 CPU 计数可能因亲和性、cgroups 或 Windows 处理器组而不同于进程可用 CPU;支撑Process.cpu_affinity()virtual_memory()swap_memory()disk_usage()
  • 版本锚定:PyPI 上 7.2.2 为当前稳定包,2026-07-23 验证。

在源码skills/get-available-resources/scripts/detect_resources.py中,psutil 是可选增强_load_psutil通过懒加载导入,导入失败只产生PSUTIL_UNAVAILABLE的 info 级警告并回退到标准库(对应 SKILL.md 的说明「The import is lazy. Failure to import psutil becomes a warning, not a fatal error」)。安装方式在 SKILL.md 中给出:

uv pip install "psutil==7.2.2"

检测器用psutil.cpu_count(logical=False)获取物理核数,用psutil.Process().cpu_affinity()作为os.sched_getaffinity的跨平台后备,用psutil.virtual_memory()psutil.swap_memory()填充主机内存与交换区字段。

Pythonos/multiprocessing/concurrent.futures

  • os文档(Python 3.14.6):支撑os.cpu_count()os.process_cpu_count()os.sched_getaffinity()。台账特意区分三者:os.cpu_count()是主机盘点,可能大于进程可用数;os.process_cpu_count()(Python 3.13+)是进程感知的。
  • multiprocessing文档(Python 3.14.6):支撑进程感知的池默认值,以及Python 3.14 在所有平台上不再默认使用fork启动方式这一变化。
  • concurrent.futures文档(Python 3.14.6):支撑ProcessPoolExecutor默认值、Windows 上 61 worker 上限ThreadPoolExecutor默认值。

这些细节直接写入了resource_semantics.md的「Python worker pools」小节:当前 Python 的multiprocessing.PoolProcessPoolExecutor在可用时使用os.process_cpu_count();依赖特定启动方式的代码必须显式请求。这解释了检测器为什么在cpu.process.python_available_logical字段中单独保留os.process_cpu_count()的观测值,并把它与affinity_logical并列——两者都是「进程视角」但来源不同的事实。

Linux:procfs 与 cgroup v2 的只读证据

台账为 Linux 平台列出了三组内核文档,恰好对应检测器在 Linux 上读取的三大类文件。

/proc文件系统

Linux 内核/proc文档支撑Cpus_allowedCpus_allowed_list的语义。检测器在_detect_process_cpu_count中优先使用os.sched_getaffinity(0)(其底层正对应内核的 CPU 亲和掩码),Cpus_allowed_list只在resource_semantics.md中被提及为/proc/self/status暴露的字段,且明确说明检测器更偏好亲和性 API 与 cgroup effective cpuset而不是直接解析该文件——这是台账「用官方文档确认字段语义、但实现选择更稳 API」的典型体现。

cgroup v2

cgroup v2 文档(页面历史可追溯至 2014-07-15)支撑了检测器在detect_cgroup_v2中读取的全部核心字段:

  • cpu.maxcpu_quota_cores:格式为$MAX $PERIODmax表示无本地带宽限制;有限比值(可能为小数)是 CPU 时间容量而非核心拓扑计数;
  • cpuset.cpus.effectivecpuset_logical:反映父级约束实际授予的 CPU,与请求的cpuset.cpus可能不同;
  • memory.current→ 当前 cgroup 用量;
  • memory.high压力/节流边界,超限不会直接触发 OOM killer,且该值可能被突破;
  • memory.max→ 硬上限,若用量无法在此边界回落,cgroup OOM killer 可能运行;
  • 层级(hierarchy)与回收(reclaim)语义 → 祖先 cgroup 会约束子级,因此检测器遍历祖先链并取最严格的有限祖先配额

源码中的实现细节:detect_cgroup_v2通过/proc/self/cgroup解析当前成员路径(脱敏后仅输出root/non_root/unknown作用域),沿祖先链至多遍历MAX_CGROUP_LEVELS = 64层,cpu_quota_coresmemory_max_bytesmemory_high_bytes均取链上有限候选的最小值——这正是「父级约束也作用于子级」语义的落地。

cpuset(cgroup v1 文档)

Linux cpuset 文档被用于交叉核对亲和掩码与 cpuset 约束的交互resource_semantics.md因此区分了三类 CPU 限制:亲和性限制「placement(放置位置)」,cpuset 限制「placement」,而cpu.max配额限制「bandwidth(带宽)」——一个 1.5 的配额是 CPU 时间容量,不是 1.5 个物理核。检测器在_effective_cpu中把主机逻辑数、进程亲和数、Python 进程计数、cgroup cpuset、cgroup 配额、调度器每进程分配全部作为候选取最小值,得到capacity_cores,并据此给出保守的worker_ceiling

容器与 OCI:配额不是默认存在的

台账引用两份容器侧文档:

  • Docker 资源约束文档:说明 Docker 容器默认没有 CPU/内存限制;配置后--cpus、quota/period、cpusets 与内存控制会映射到 cgroup 控制;
  • OCI Runtime Specification 1.3.0:定义 CPU、内存、cgroup 与设备资源的语义。

这支撑了resource_semantics.md中「Container markers identify context; cgroup controls identify limits」的区分:容器标记(/.dockerenv/run/.containerenv)只说明上下文,而没有有限 cgroup 值的容器标记不意味着存在有限限制。检测器_container_context的实现即体现了这一点:只有同时存在 marker 且观察到有限 cgroup 约束(cpu_quota_cores/cpuset_logical/memory_max_bytes)时,cgroup_limit才作为证据出现;detected布尔值仅由 marker 决定。容器内主机盘点仍可见、CPU 配额可小于可见 CPU 集、cpuset 可小于配额表观容量、cgroup 内存可小于宿主机 RAM——这些都在resource_semantics.md中被列为必须报告的观测事实。

NVIDIA:管理可见性与运行时兼容性是两件事

台账的 NVIDIA 部分支撑了检测器对 GPU 的「候选」而非「可用」定位,共四条来源:

  • nvidia-smi 手册:固定--query-gpu字段与--format=csv,noheader,nounits格式;并指出index 排序不稳定,因此快照不声称持久身份,只输出局部查询索引local_index
  • NVIDIA Container Toolkit 文档NVIDIA_VISIBLE_DEVICES、驱动能力(driver capabilities)与运行时约束;
  • CUDA_VISIBLE_DEVICES 部署文档:CUDA 应用可见性;
  • CUDA 兼容性文档:区分管理可见性兼容的 GPU、驱动、CUDA 运行时、动态链接库

检测器中的证据(scripts/detect_resources.py):

NVIDIA_QUERY = ( "nvidia-smi", "--query-gpu=index,name,memory.total,memory.free,driver_version,compute_cap", "--format=csv,noheader,nounits", )

parse_nvidia_csv只从 CSV 行中提取白名单字段;每个设备固定输出device_permission: not_testedruntime_compatibility: not_testedresource_semantics.md明确:nvidia-smi成功只证明 NVIDIA管理可见性,不证明 CUDA 库存在或兼容。因此runtime_usable_devices字段始终为nullcandidate_upper_bounds只是可见性/分配计数的上界。

AMD ROCm:主工具与只读回退

  • AMD SMI 7.2.0:只读list/staticJSON 输出及其「不可用字段」的含义;
  • ROCm SMI 文档:遗留rocm-smi只读回退用法;
  • ROCm 7.2.4 GPU 隔离ROCR_VISIBLE_DEVICESHIP_VISIBLE_DEVICESCUDA_VISIBLE_DEVICES、Docker 设备隔离,以及「环境变量对不可信代码不是隔离手段」的警告;
  • ROCm 环境变量文档:AMD 在 Linux/Windows 上可见性变量的推荐用法(Linux 推荐ROCR_VISIBLE_DEVICES,Windows 推荐HIP_VISIBLE_DEVICES)。

源码_detect_accelerators体现了「主工具优先、遗留回退」:先跑amd-smi static --json,仅当未找到或失败时才回退到rocm-smi --showproductname --showmeminfo vram --json,并分别在 provenance 中记录实际使用的工具名。parse_amd_json以容错方式递归提取asic_market_name/card_model等白名单名称键与 VRAM 容量,任何解析失败只影响该设备,不会抹掉其他成功观测。

Apple:统一内存与可解析的系统查询

  • Apple「Determining system capabilities」hw.logicalcpuhw.physicalcpuhw.memsize、性能层级(performance levels),以及逻辑核与物理核的区分;
  • Applesysctl(3)手册:交叉核对物理内存字段;
  • Apple DTS 答复(2021-08-24)system_profiler输出可解析,但DIMM 式细节不能干净地映射到集成内存或 Apple silicon 内存

检测器固定使用两条只读命令:sysctl -n hw.logicalcpu hw.physicalcpu hw.memsize machdep.cpu.brand_stringsystem_profiler SPDisplaysDataType -json。台账还记录了本地冒烟测试:这些固定查询于 2026-07-23 在 Darwin 25.5.0 上验证通过,且脚本从不请求完整系统配置(never requests the full system profile)。

Apple silicon 上memory.modelunified_cpu_gpu:CPU 与集成 GPU 共享统一内存,检测器不会把虚构的 GPU VRAM 加到系统 RAM 上,也不把集成 GPU 描述为独立 VRAM。Apple 集成 GPU 只作为Metal 候选,与 CUDA/ROCm 候选严格区分。

Slurm:分配变量 ≠ 强制执行的证明

台账为 Slurm 列出了五个文档条目,共同支撑「调度器分配需要站点配置才真正执行」的核心语义:

  • sbatch:精确的分配环境变量作用域——SLURM_CPUS_ON_NODESLURM_CPUS_PER_TASKSLURM_JOB_CPUS_PER_NODESLURM_MEM_PER_CPUSLURM_MEM_PER_NODESLURM_NTASKS与 GPU 变量;并明确警告内存请求需要站点配置 enforcement 才有效
  • CPU Management Guidetask/affinitytask/cgroupConstrainCores、绑定与逻辑 CPU/核心分配示例;
  • srun:任务限制与 GPU 绑定行为;
  • scontrol:只读scontrol show job的解释工作流;
  • sstat:作业步骤启动后的记账(accounting)语义。

检测器detect_scheduler只读取SLURM_ENV_KEYS白名单中的命名变量(共 15 个,见源码第 79–95 行),绝不转储环境。它解析出的字段包括:

变量语义作用域(来自台账/语义文档)
SLURM_CPUS_PER_TASK每任务请求 CPU,适合作单个任务进程的每进程上界
SLURM_CPUS_ON_NODE当前批处理步骤在节点上分配的 CPU,可在任务间共享
SLURM_JOB_CPUS_PER_NODE每节点分配列表,不是进程计数
SLURM_MEM_PER_CPU每个分配 CPU 的内存;仅当每任务 CPU 数已知时才成为每任务边界
SLURM_MEM_PER_NODE每节点共享内存上界
SLURM_GPUS_PER_TASK每任务请求 GPU
SLURM_GPUS_ON_NODE节点上批处理步骤分配的 GPU

实现上,cpu_per_process优先取SLURM_CPUS_PER_TASK;仅当SLURM_CPUS_ON_NODE存在且tasks_per_node == 1时才用节点数作每进程数。内存上界只有在memory_per_cpu × cpu_per_process可解释时才按「每任务」计,否则按「共享每节点」并给出SLURM_MEMORY_SHARED警告。输出中enforcement恒为unknownnot_applicable,并固定产生SLURM_ENFORCEMENT_UNKNOWN提示——因为「分配变量不能证明亲和性或 cgroup 强制执行」,这正是scontrol/sstat条目所要传达的事实边界。

Windows:处理器组的作用域差异

  • Microsoft Processor Groups 文档:系统逻辑处理器、物理核与处理器组调度的区分;
  • GetLogicalProcessorInformation:逻辑/物理关系,以及超过 64 个逻辑处理器的系统上当前组的限制
  • GetLogicalProcessorInformationEx(页面日期 2023-03-06):系统级处理器组拓扑。

这解释了resource_semantics.md中的警告:在多处理器组 Windows 系统上,系统级逻辑计数与单进程/线程组可用计数可能不同。这也是「可选 psutil 提升物理核、亲和性、可用内存与交换区观测」在 Windows 上更有价值的原因(见 SKILL.md 的 Platform notes),以及检测器为何在 CPU 部分同时维护host.logicalprocess.affinity_logical两个独立事实。

台账如何映射到快照字段

将台账来源与skills/get-available-resources/references/snapshot_schema.md定义的 schema 1.1 对照,可以清晰看到每个字段背后的依据来源:

快照字段主要来源依据关键语义
cpu.host.logical / physicalpsutil、Apple sysctl、Linux/proc/cpuinfo主机盘点,物理核绝不从逻辑数推断
cpu.process.affinity_logicalos.sched_getaffinity/ psutilcpu_affinity当前进程可放置的 CPU 集合大小
cpu.cgroup_v2.quota_corescgroup v2cpu.max最严格有限祖先配额,可为小数
cpu.effective.capacity_cores六类候选取最小值最小正观测约束,不叫物理核数
memory.effective.hard_limit_bytespsutil / cgroupmemory.max/ Slurm有限主机、cgroup、调度器的最小值
memory.effective.pressure_threshold_bytescgroupmemory.high节流边界,重新标记为硬上限
memory.modelApple 文档Apple silicon 为unified_cpu_gpu
accelerators.devices[*].runtime_compatibilityNVIDIA CUDA 兼容性、ROCm 隔离文档恒为not_tested
scheduler.enforcementSlurm sbatch/CPU Management Guide恒为unknown/not_applicable
disk.user_available_bytesPOSIXf_bavail语义(psutil/shutil用户可用块,可能小于 free 块

schema 文档还明确了null0的区分:null表示不可用,既不是零也不是无限0只在来源明确建立零时才使用(例如某个可见性变量明确隐藏了全部设备)。这条规则与台账「Missing evidence means unknown」一脉相承。

何时、如何刷新这份台账

SKILL.md 给出了明确的维护契约:官方文档于2026-07-23刷新,在修改语义或依赖锁定前必须查阅sources.md。结合台账自身格式,合理的刷新流程是:

  1. 对每条 living docs 重新核验访问日期,更新「研究截止」;
  2. 对版本化来源(psutil 7.2.2、Python 3.14.6、OCI 1.3.0、AMD SMI 7.2.0、ROCm 7.2.4、GetLogicalProcessorInformationEx的 2023-03-06 页面日期等)确认是否有新版本改变了语义结论;
  3. detect_resources.py中同步任何受影响的探测参数(例如NVIDIA_QUERY的字段、SLURM_ENV_KEYS白名单)或snapshot_schema.md的字段契约;
  4. 跑一遍仓库根目录tests/get-available-resources/下的离线测试用例(test_scripts.pyfixtures/resource_cases.json),确认 Linux/macOS/Windows/cgroup/Slurm/加速器各分支行为不回退。

这种「先查台账、再改语义、最后跑测试」的顺序,保证了技能在跨平台、跨版本演进时不会悄悄改变nullnot_testedunknown这类保守约定的含义。

结语

references/sources.md的价值不在罗列链接,而在于它把每一个保守决策(不推断物理核、不把memory.high当硬限、不把管理可见性当运行时可用、不把分配变量当强制证据)都锚定到可复核的官方依据上。配合resource_semantics.md的解释规则、snapshot_schema.md的字段契约、detect_resources.py的实现与仓库根目录tests/get-available-resources/的测试,这份台账构成了 get-available-resources 技能「事实准确、边界清晰、可追溯」的完整证据链。对任何想要在自己的 Agent 或科学计算工作流中复用它的人来说,从这份台账开始理解其语义边界,是最稳妥的切入点。

【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000+ scientists worldwide. 165 ready-to-use validated skills plus 100+ scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询