CentOS7部署Ollama本地大模型:从零到一的完整踩坑指南
2026/9/16 20:03:28
spmd(Single Program Multiple Data)是并行计算工具箱(Parallel Computing Toolbox)提供的核心并行编程结构,用于在多个工作进程(workers)上同时执行相同的代码,但操作不同的数据。它特别适用于需要分布式内存并行的场景(如大型数组分块、多节点协同计算)。parfor(共享内存、任务并行)不同,spmd是分布式内存模型,适合处理超出单机内存的大规模数据。| 变量 | 含义 |
|---|---|
labindex | 当前 worker 的编号(从 1 到numlabs) |
numlabs | 总 worker 数量(由parpool决定) |
spmdIndex | 同labindex(旧版名称) |
Composite | 一种特殊数据类型,用于在 workers 间交换数据 |
spmd块时,MATLAB 会:gplus,gop,drange)交换数据。Composite对象形式返回到客户端。spmd% 在所有 worker 上并行执行的代码% labindex: 当前 worker ID (1, 2, ..., numlabs)% numlabs: 总 worker 数end⚠️ 注意:
spmd必须在已启动的并行池(parpool)中运行。
parpool(4);% 启动 4 个 workerspmdfprintf('Hello from worker %d of %d\n',labindex,numlabs);end输出(顺序可能不同):
Hello from worker 1 of 4 Hello from worker 2 of 4 Hello from worker 3 of 4 Hello from worker 4 of 4spmd local_data=rand(1000,1);% 每个 worker 生成自己的数据local_sum=sum(local_data);% 局部求和total_sum=gplus(local_sum);% 全局归约(所有 worker 的 local_sum 相加)end% 客户端获取结果total_sum_client=total_sum{1};% 所有 worker 的 total_sum 相同使用distributed将大数组自动分块到各 worker,避免手动管理。
spmd% 创建一个 1000x1000 的分布式随机矩阵D=distributed.rand(1000);% 每个 worker 只存储自己的分块myPart=getLocalPart(D);% 获取当前 worker 的数据块% 对局部数据操作localMax=max(myPart(:));% 全局最大值globalMax=gop(@max,localMax);end% 客户端收集结果globalMax_val=globalMax{1};✅ 优势:自动处理数据分布、通信和聚合,代码简洁。
codistributed)当需要非均匀分块(如按列、按行、自定义分区)时:
spmd% 创建一个 4x4 矩阵,按列分布(每列给一个 worker)iflabindex<=4localData=repmat(labindex,4,1);% 第 i 列全为 ielselocalData=[];% 多余 worker 无数据end% 构建 codistributed 数组dim=2;% 按第2维(列)分布codist=codistributor1d(dim,[],[4,4]);% [4,4] 是全局尺寸C=codistributed.build(localData,codist);end% 客户端查看完整矩阵fullMatrix=gather(C);labSend,labReceive)实现非集体通信(如 worker 1 → worker 2 发送数据):
spmdiflabindex==1dataToSend=42;labSend(dataToSend,2);% 发送给 worker 2elseiflabindex==2receivedData=labReceive(1);% 从 worker 1 接收fprintf('Worker 2 received: %d\n',receivedData);endend⚠️ 注意:必须确保发送/接收配对,否则会死锁。
gplus,gop,gcat)gplus(X):所有 worker 的X相加(等价于gop(@plus, X))gop(@max, X):全局最大值gcat(X, dim):沿维度dim拼接所有 worker 的Xspmd localVec=(labindex-1)*10+(1:5);% worker1: [1..5], worker2: [11..15], ...globalVec=gcat(localVec,2);% 水平拼接 -> [1..5, 11..15, ...]end% 客户端result=globalVec{1};% 所有 worker 的 globalVec 相同spmd块结尾自动同步所有 worker。spmd块失败。spmdtry% 可能出错的操作result=some_risky_computation();catchME% 记录错误(但无法恢复)error('Worker %d failed: %s',labindex,ME.message);endendspmdvsparfor对比| 特性 | spmd | parfor |
|---|---|---|
| 内存模型 | 分布式(每个 worker 独立内存) | 共享(worker 间无直接内存访问) |
| 适用场景 | 大规模数据分块、通信密集型 | 任务并行、无依赖循环 |
| 数据交换 | 显式通信(gplus,labSend) | 通过 sliced/reduction 变量隐式 |
| 编程复杂度 | 较高(需管理分布) | 较低 |
| 典型用途 | 分布式线性代数、PDE 求解 | 参数扫描、蒙特卡洛模拟 |
gop/labSend调用。spmd块内避免动态扩容数组。distributed+ 内置操作(如sum(D,1)),而非手动gplus。functionC=distributed_matmul(A,B)% A: MxK, B: KxN -> C: MxN[M,K]=size(A);[~,N]=size(B);spmd% 按行分布 A,按列分布 BA_dist=codistributed(A,codistributor1d(1));% 按行分B_dist=codistributed(B,codistributor1d(2));% 按列分% 每个 worker 计算局部 C_block = A_block * B_blockC_local=A_dist*B_dist;% 归约:所有 worker 的 C_local 相加(因为每个 block 覆盖不同区域)C_dist=gplus(C_local);end% 客户端收集结果C=gather(C_dist);end💡 实际中应使用
codistributed的更高效分块策略(如 2D 分块)。
spmd是 MATLAB 中实现分布式内存并行的核心工具。labindex/numlabs、Composite/distributed数据类型、以及通信原语(gplus,labSend)。parfor互补:parfor用于任务并行,spmd用于数据并行。📌最佳实践:优先使用
distributed数组 + 内置操作,避免手动管理通信,除非有特殊需求。