mcpField
M
matlab-discover-clusters

matlab-discover-clusters

github.com/matlab云与 DevOps1.2k66 次安装2 天前更新
代码仓库

关于 matlab-discover-clusters

面向 MATLAB 并行计算用户的技能,覆盖集群配置文件的发现、导入、检查、设为默认和删除,并指导验证可用性。

主要功能

  1. 01列出并检查集群配置文件
  2. 02发现网络及云端集群
  3. 03导入与导出共享配置文件
  4. 04设置默认配置并验证
  5. 05删除过时配置文件

适用场景

  1. 01查找可提交作业的集群资源
  2. 02导入管理员提供的 .mlsettings 文件
  3. 03确认 parcluster 或 parpool 使用的配置
  4. 04将配置文件分享给同事

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/matlab/matlab-agentic-toolkit --skill matlab-discover-clusters

安装后在 Claude Code 中输入/matlab-discover-clusters确认已加载。

附带文件manifest.yamlscripts/discoverClusters.p

详细介绍

发现 MATLAB 集群

集群配置文件是一组已保存的属性(名称、类型、主机、工作进程数、调度器参数),可让 MATLAB 连接到计算资源。本技能涵盖配置文件的完整生命周期:发现网络上的集群、导入共享配置文件、设置默认配置文件、验证和删除。

适用场景

  • 用户询问有哪些并行计算资源、集群或队列可供使用。
  • 用户想查找可用于提交作业的集群。
  • 用户从管理员处获得了 .mlsettings 配置文件,需要导入。
  • 用户想列出、检查、设为默认、验证或删除集群配置文件。
  • 用户想导出集群配置文件并与同事共享。
  • 用户正在调用 parcluster 或 parpool,想知道将使用哪种资源,或应传入哪个配置文件名称。

不适用场景

  • 提交作业(batch、createJob、submit、parfeval)——本技能仅涵盖到“集群已准备就绪,可供使用”为止。
  • 超出配置文件选择范围的池生命周期管理——parpool 启动/关闭、gcp 和销毁池属于其他问题。确定传给 parpool 的配置文件属于本技能范围。
  • GPU 或 parfor 工作流——由单独的技能涵盖。

工作流

  1. 使用 parallel.listProfiles 列出现有配置文件,查看已配置的内容。
  2. 如果用户缺少预期资源,或想搜索其他集群,请使用随附的 discoverClusters 脚本发现集群(网络和云)。
  3. 将集群添加为配置文件——可以根据发现的集群创建配置文件(saveAsProfile),也可以导入共享的 .mlsettings 文件(parallel.importProfile)。
  4. 如果合适,使用 parallel.defaultProfile 设置默认配置文件。
  5. 使用 parallel.validateProfile(R2025a+)或对集群对象调用 validate(c) 进行验证,然后再依赖该配置文件。传入 NumWorkersToUse(例如 2),或先向用户确认——如果不设置此项,将使用集群的全部工作进程数进行验证。
  6. 使用 parallel.deleteProfile(R2026a+)删除过时的配置文件——请先向用户确认;删除操作不可撤销。

每完成一步,都要先验证再继续——显示更新后的配置文件列表、确认类型/主机/工作进程数,或检查验证报告。

主要函数

函数用途起始版本
parallel.listProfiles列出配置文件名称和默认配置文件R2022b
parallel.defaultProfile获取或设置默认配置文件R2022b
parallel.importProfile从 .mlsettings 导入配置文件R2022b
parallel.exportProfile将配置文件导出为 .mlsettingsR2022b
parcluster根据配置文件创建集群对象R2022b
cluster.saveAsProfile将集群对象保存为新配置文件R2022b
parallel.validateProfile验证配置文件(独立函数)R2025a
validate(cluster)通过集群对象进行验证R2026a
parallel.deleteProfile按名称删除配置文件R2026a
discoverClusters随本技能提供——发现 MJS / Generic / HPCServer / MJSComputeCloudscripts/discoverClusters.p
cluster.Type属性:"Local"、"Threads"、"MJS"、"MJSComputeCloud"、"Slurm"、"PBSPro"、"LSF"、"HPCServer"、"Generic"R2022b

对于高于 R2022b 最低版本要求的功能,请使用模式中注明的备用方案,并向用户说明版本差异。

使用模式

列出和检查配置文件

使用 parallel.listProfiles 获取配置文件名称,并使用 parallel.defaultProfile()(不带参数)读取默认配置文件。若要检查某个配置文件,请调用 parcluster(name) 并读取 cluster.Type(字符串)、cluster.NumWorkers,以及(如适用)cluster.Host。不要解析 class(c)——Type 才是受支持的公开属性。

parcluster(name) 会针对 MJS 配置文件进行一次网络往返,以从调度程序获取实时属性。如果无法访问 MJS,或其发行版不匹配,则会抛出 "Unable to connect to MATLAB Job Scheduler"——这是预期行为,不是代码错误。遍历配置文件时,务必将 parcluster 包在 try/catch 中,并明确区分无法访问的配置文件和不存在的配置文件。

Threads 配置文件无法通过 parcluster 返回——请明确跳过。

使用 strcmp(或两个 string)比较配置文件名称,不要使用 ==:使用 == 比较两个 char 数组会逐字符比较,且当长度不同时会报错。

profiles = parallel.listProfiles;
defaultName = parallel.defaultProfile();

fprintf("\n%-25s %-10s %-10s  %s\n", "Profile", "Type", "Workers", "Default");
fprintf("%s\n", repmat('-', 1, 70));
for k = 1:numel(profiles)
    name = profiles{k};
    marker = "";
    if strcmp(name, defaultName); marker = "(default)"; end
    if strcmp(name, "Threads")
        fprintf("%-25s %-10s %-10s  %s\n", name, "Threads", "n/a", marker);
        continue
    end
    try
        c = parcluster(name);
        fprintf("%-25s %-10s %-10d  %s\n", name, string(c.Type), c.NumWorkers, marker);
    catch
        fprintf("%-25s %-10s %-10s  %s\n", name, "?", "?", marker + " unreachable");
    end
end
发现 MJS、Generic、HPCServer 和 MJSComputeCloud 集群

discoverClusters 位于此技能的 scripts/ 文件夹中。首次使用前,请将其添加到路径中:

addpath(fullfile(skillRoot, "scripts"));   % skillRoot = directory containing this SKILL.md

随附的 discoverClusters 函数封装了与 MATLAB Cluster Profile Manager UI 使用的相同内部发现基础设施。它会返回一个结构体数组,每个已发现的集群对应一个条目:

clusters = discoverClusters();                                  % all scopes, 30s timeout
% Other forms:
%   discoverClusters(Scope="network", TimeoutSeconds=15)
%   discoverClusters(Scope="cloud")

每个条目包含以下字段:Type、Name、Host、NumWorkers、MatlabRelease、IsCompatible、CorrespondingProfiles 和 Properties(一个按名称索引、包含所有已发现属性的结构体)。对于 Generic 集群,Properties 包含 PluginScriptsLocation、JobStorageLocation、AdditionalProperties 等——即构建集群所需的所有内容。

简要显示发现结果,并指出 IsCompatible == false(发行版不匹配)的情况,以及任何已设置 CorrespondingProfiles 的集群(表示已导入)。

clusters = discoverClusters();

if isempty(clusters)
    disp("No clusters discovered.");
    return
end

fprintf("Discovered %d clusters:\n", numel(clusters));
for k = 1:numel(clusters)
    profileNote = "no profile";
    if ~isempty(clusters(k).CorrespondingProfiles)
        profileNote = "profile: " + strjoin(string(clusters(k).CorrespondingProfiles), ", ");
    end
    compatNote = "compatible";
    if ~clusters(k).IsCompatible
        compatNote = "INCOMPATIBLE (" + clusters(k).MatlabRelease + ")";
    end
    fprintf("  [%d] %s '%s' on %s — %s, %s\n", ...
        k, clusters(k).Type, clusters(k).Name, clusters(k).Host, ...
        compatNote, profileNote);
end

不要退而使用特定于平台的 CLI 工具(nodestatus、mjs status)或杜撰的 API(parallel.cluster.find、parallel.cluster.discover、findResource)。请使用 discoverClusters——这些替代方案要么不存在,要么会绕过受支持的发现基础设施。

如果 discoverClusters 未返回任何结果,并不意味着用户没有集群——并非每个 Generic 集群都配置了可供发现的 .conf 文件。建议用户联系集群管理员,获取可供导入的 .mlsettings 配置文件。

将发现的 MJS 集群另存为配置文件

发现后,使用 parallel.cluster.MJS(Name=, Host=) 构造 MJS 集群,并调用 saveAsProfile(name)。saveAsProfile 是 void——不要赋值其返回值。

parallel.cluster.MJS(Name=,Host=) 会连接到 MJS 查找服务,以验证集群并获取实时属性——这并不是一种开销很小的对象构造操作。如果集群无法访问,该调用会抛出 "Unable to connect to MATLAB Job Scheduler"。

客户端连接时,MJS 集群可能会在 MATLAB 对话框中提示输入凭据,有两种情况:集群的 SecurityLevel 非零,或集群需要在线许可。用户响应前,对话框会阻塞 parallel.cluster.MJS(...);如果用户关闭对话框但未输入凭据,调用会报错:"Operation aborted because no credentials were entered for user ..."。运行任何会构造 MJS 集群对象的代码前,明确警告用户:"即将连接到 MJS 集群 <Name>——请立即切换到 MATLAB;可能会出现凭据对话框,并且该命令会一直阻塞,直到你响应。"如果未发现 MJS 集群,或当前操作不涉及 MJS 集群,则不要发出此警告——Generic、HPCServer、Local 和 Threads 配置文件不会通过这种方式进行身份验证。

始终先按 Type=="MJS" 过滤发现的集群,再采用此模式——发现结果还会包含 Generic / HPCServer / MJSComputeCloud 条目,而对 Slurm 头节点调用 parallel.cluster.MJS 会产生令人困惑的连接错误。

clusters = discoverClusters(Scope="network");

% Pick the first compatible MJS without an existing profile.
isMJS = string({clusters.Type}) == "MJS";
target = clusters(find(isMJS & [clusters.IsCompatible] & ...
    cellfun(@isempty, {clusters.CorrespondingProfiles}), 1));

c = parallel.cluster.MJS(Name=target.Name, Host=target.Host);
c.saveAsProfile(target.Name);
fprintf("Saved profile '%s'\n", target.Name);

调用 saveAsProfile(name) 前,检查 parallel.listProfiles——如果 name 已被占用,请询问用户选择其他名称(例如,加入主机名),而不要静默覆盖或创建重复项。

将发现的 Generic(Slurm/PBS/LSF)集群另存为配置文件

Generic 集群通过基于文件系统的发现机制呈现——管理员会提供描述调度器的 .conf 文件,发现机制会从 matlabroot/toolbox/parallel/user/clusterprofiles、$MATLAB_CLUSTER_PROFILES_LOCATION、$HOME 或 $HOME/Downloads 中找到它。发现条目上的 Properties 结构体包含 parallel.cluster.Generic 对象所需的一切信息。

parallel.cluster.Generic 没有 Name 属性——配置文件名称通过 saveAsProfile 传入。

clusters = discoverClusters();
target = clusters(find(string({clusters.Type}) == "Generic" & ...
    [clusters.IsCompatible], 1));
p = target.Properties;

c = parallel.cluster.Generic;
c.NumWorkers = double(p.NumWorkers);
c.JobStorageLocation = char(p.JobStorageLocation);
c.PluginScriptsLocation = char(p.PluginScriptsLocation);
c.ClusterMatlabRoot = char(p.ClusterMatlabRoot);
c.OperatingSystem = char(p.OperatingSystem);
c.HasSharedFilesystem = logical(p.HasSharedFilesystem);
c.RequiresOnlineLicensing = logical(p.RequiresOnlineLicensing);

if isfield(p, 'AdditionalProperties')
    apFields = fieldnames(p.AdditionalProperties);
    for k = 1:numel(apFields)
        c.AdditionalProperties.(apFields{k}) = p.AdditionalProperties.(apFields{k});
    end
end

c.saveAsProfile(char(p.Name));

同一模式适用于通过 .conf 发现的任何第三方调度器(Slurm、PBS Pro、LSF、Grid Engine、HTCondor)——Type 始终为 Generic;调度器由 PluginScriptsLocation 的内容标识。

导入共享配置文件、设为默认配置并验证
profileName = parallel.importProfile("team_cluster.mlsettings");
parallel.defaultProfile(profileName);
parallel.validateProfile(profileName);

parallel.importProfile 会返回已导入配置文件的名称。parallel.defaultProfile 带一个参数时会设置默认配置,但不会返回有用内容——不带参数调用 parallel.defaultProfile() 才能读取默认配置。

验证集群(分阶段)

使用 parallel.validateProfile(R2025a+)。它接受 StagesToRun、StagesToSkip、NumWorkersToUse 和 ReportFile 名称-值参数。此函数没有输出参数——验证会打印报告,并在请求时写入 ReportFile。

对于新发现或共享的集群,始终传入 NumWorkersToUse——否则验证会使用全部工作进程运行,这通常不是用户所希望的;而在共享集群上(例如 MJSComputeCloud 或站点 MJS),还会占用其他用户可能正在等待使用的资源。使用整个集群进行验证前,请先向用户确认。

parallel.validateProfile("myProfile", ...
    StagesToRun=["parcluster", "job", "parpool"], ...
    NumWorkersToUse=4, ...
    ReportFile="validation-report.txt");

有效阶段(适用于大多数集群类型):"parcluster"、"job"、"spmd-job"、"pool-job"、"parpool"。具体集合因集群 Type 而异——仅 Threads 的配置文件可验证的阶段较少。

在 R2026a+ 中,也可以通过集群对象使用 validate(cluster) 设置相同选项:

c = parcluster("myProfile");
validate(c, StagesToRun=["parcluster", "job", "parpool"]);

对于低于 R2025a 的版本,没有可编写脚本调用的验证 API——请引导用户使用集群配置文件管理器 UI(Home > Parallel > Create and Manage Clusters),并说明该版本限制。

删除配置文件

删除前务必先向用户确认——parallel.deleteProfile 不可撤销。先列出配置文件,并向用户复述要删除的目标。

parallel.deleteProfile("oldCluster");

对于 R2026a 之前的版本,没有可用的公共函数。请引导用户使用 Cluster Profile Manager UI(Home > Parallel > Create and Manage Clusters 或 parallel.gui.ProfileManager.start)。

约定

  • 务必在修改前读取配置文件列表:使用 parallel.listProfiles 查看现有配置文件,然后调用 parallel.defaultProfile()(不带参数)查看默认配置文件。
  • 务必在将发现的集群保存为配置文件之前验证 IsCompatible——版本不匹配会导致提交作业失败,而非创建配置文件失败。
  • 务必使用 cluster.Type 识别集群类型——绝不要使用 class(c)。
  • 务必在遍历配置文件时,用 try/catch 包装 parcluster(name)——对于 MJS 配置文件,它会执行网络往返;如果服务器无法访问或版本不匹配,就会失败。
  • 务必使用 strcmp(或两个 string)比较配置文件名称,而不要使用 ==。parallel.listProfiles 返回 char 元素组成的元胞数组,而两个长度不同的 char 数组之间使用 == 会报错。
  • 务必在验证刚发现或共享的集群时,将 NumWorkersToUse 限制为较小的数值(例如 2),或先向用户确认工作进程数量——如果不设置,验证会使用集群的全部工作进程。
  • 务必在删除配置文件前向用户确认——parallel.deleteProfile 不可撤销。
  • 务必在调用 saveAsProfile(name) 前检查 parallel.listProfiles。如果 name 已被占用,请向用户询问其他名称,而不要覆盖或创建重复配置文件。
  • 优先使用 parallel.listProfiles,而不是已弃用的 parallel.clusterProfiles。
  • 优先使用 parallel.defaultProfile,而不是已弃用的 parallel.defaultClusterProfile。
  • 优先使用 parallel.validateProfile(R2025a+)——它不需要先构造集群对象。validate(cluster) 提供相同的选项,但直到 R2026a 才推出;在 R2025a 中,请使用独立函数或 GUI。

常见错误

错误为什么不对正确做法
parallel.clusterProfiles自 R2022b 起已弃用(仍可使用,但不推荐)。parallel.listProfiles
parallel.defaultClusterProfile(name)自 R2022b 起已弃用。parallel.defaultProfile(name)
使用 class(c) 识别集群类型返回 MATLAB 类名称('parallel.cluster.Local'),而不是配置文件类型。c.Type(返回 "Local"、"MJS" 等)
parallel.cluster.find、parallel.cluster.discover、findResource这些函数都不存在。discoverClusters(随此技能打包提供)
通过 system() 调用 nodestatus这是 CLI 工具,依赖平台,不受 API 支持。discoverClusters
parallel.cluster.removeProfile、parallel.removeProfile虚构的名称——这两个函数都不存在。parallel.deleteProfile(R2026a+)
[ok, msg] = validate(c)validate 没有输出参数。调用 validate(c)(或 parallel.validateProfile),并检查打印出的报告或 ReportFile。
name = c.saveAsProfile(name)saveAsProfile 不返回值——没有输出参数。调用 c.saveAsProfile(name),不要赋值。
在 parallel.cluster.Generic 上设置 c.NameGeneric 没有 Name 属性——保存配置文件时才会设置 Name。配置属性,然后调用 c.saveAsProfile("<name>")。
对 Threads 配置文件调用 parclusterparcluster 无法返回 Threads 配置文件。遍历配置文件时跳过 Threads。

脚本

  • scripts/discoverClusters.p — 使用与 Cluster Profile Manager UI 相同的基础设施发现集群。返回一个结构体数组,包含 Type、Name、Host、NumWorkers、MatlabRelease、IsCompatible、CorrespondingProfiles。名称-值选项:Scope("all"/"network"/"cloud",默认值为 "all")、TimeoutSeconds(默认值为 30)。

Copyright 2026 The MathWorks, Inc.


评论

支持 Markdown