Master地址和端口:Driver vs Executor
问题的核心
在Spark cluster模式下,有两个层面的"master":
- Spark的Driver(主节点)
- DDP的Master进程
它们完全不同!
两套Master系统
1. Spark的Driver(与我们的DDP无关)
Spark集群架构:
┌─────────────────────────────────────────────┐
│ Driver (主节点) │
│ - 运行在集群的某个节点上 │
│ - IP: 192.168.1.100 │
│ - 负责提交任务和管理资源 │
│ - 与Executor通信 │
└─────────────────────────────────────────────┘
↓ (提交任务)
┌─────────────────────────────────────────────┐
│ Executor (工作节点) │
│ - 动态分配到集群 │
│ - IP: 10.0.0.5 (每次可能不同) │
│ - 执行具体的训练任务 │
└─────────────────────────────────────────────┘
2. DDP的Master(我们当前配置的)
Executor内部(Executor IP = 10.0.0.5):
┌─────────────────────────────────────────────┐
│ torchrun Master │
│ - 运行在Executor内部 │
│ - 地址: localhost │
│ - 端口: 23456 │
│ - 协调DDP进程间的通信 │
└─────────────────────────────────────────────┘
↓ (DDP通信)
┌─────────────────────────────────────────────┐
│ Process 0 (rank 0) ←─┐ │
│ Process 1 (rank 1) ←─┼──→ 连接到 │
│ Process 2 (rank 2) ←─┤ localhost:23456 │
│ Process 3 (rank 3) ←─┘ │
└─────────────────────────────────────────────┘
关键答案
master_addr和master_port是指Executor内部的DDP Master,与Spark Driver无关!
详细解释
Spark架构(Driver-Executor通信)
Driver (主节点)
├─ 功能:提交任务、管理资源、收集结果
├─ 通信:与Executor通过Spark RPC通信
└─ 地址:由Spark自动管理,我们不需要关心
↓
Executor (工作节点)
├─ 功能:执行任务
├─ 通信:接收Driver的命令,发送结果给Driver
└─ 地址:动态分配,我们不需要知道
DDP架构(进程间通信)
Executor内部(只有这里用master_addr/master_port)
├─ torchrun启动Master进程
│ └─ 监听 localhost:23456
├─ Process 0 连接 localhost:23456
├─ Process 1 连接 localhost:23456
├─ Process 2 连接 localhost:23456
└─ Process 3 连接 localhost:23456
关键点:
- ✅
master_addr=localhost(Executor内部的地址) - ✅
master_port=23456(Executor内部的端口) - ❌ 与Driver无关
- ❌ 与Executor的外部IP无关
为什么使用localhost?
层级结构
┌─────────────────────────────────────────┐
│ Spark Driver │
│ - 管理整个Spark应用 │
│ - 不参与DDP训练 │
└──────────┬──────────────────────────────┘
│ Spark提交任务
↓
┌─────────────────────────────────────────┐
│ Executor (独立容器) │
│ IP: 10.0.0.5 (外部) │
│ │
│ ┌─────────────────────────────────┐ │
│ │ DDP Master (torchrun) │ │
│ │ 监听: localhost:23456 │ │
│ │ │ │
│ │ ┌─────────┐ │ │
│ │ │ Process │ ←─连接到localhost │ │
│ │ │ 0-3 │ :23456 │ │
│ │ └─────────┘ │ │
│ └─────────────────────────────────┘ │
│ │
│ 所有DDP通信在Executor内部进行 │
│ 使用localhost,不涉及外部网络 │
└─────────────────────────────────────────┘
localhost的作用域
Executor外部:
├─ Spark集群看到 Executor IP = 10.0.0.5
└─ 但与DDP无关
Executor内部:
├─ DDP使用 localhost (127.0.0.1)
├─ 所有进程在同一台机器上
└─ 通过本地回环接口通信
配置的位置
当前配置分析
python
# spark_train_ddp_wrapper.py
# 这个脚本运行在哪里?→ Executor上!
def main():
# 在Executor上运行的代码
torchrun_cmd = [
'--master_addr', 'localhost', # Executor内部地址
'--master_port', '23456', # Executor内部端口
]
运行位置:
- Spark将
spark_train_ddp_wrapper.py提交到Executor - 脚本在Executor上执行
- master_addr和master_port用于Executor内部的DDP通信
- 与Driver完全无关
执行流程
完整的执行链路
┌──────────────────────────────┐
│ 你在本地机器上 │
│ $ ./spark_submit_hourly_ddp.sh
└──────────┬───────────────────┘
↓ spark-submit提交
┌──────────────────────────────┐
│ Spark Driver │
│ (某个节点的192.168.1.100) │
│ - 接收任务 │
│ - 分配资源 │
│ - 提交到Executor │
│ - (不参与DDP训练) │
└──────────┬───────────────────┘
↓ 分配给Executor
┌──────────────────────────────┐
│ Executor │
│ (随机IP,如10.0.0.5) │
│ - 运行spark_train_ddp_ │
│ wrapper.py │
│ │
│ torchrun启动DDP: │
│ ├─ Master监听 │
│ │ localhost:23456 │
│ ├─ Process 0 → localhost: │
│ │ 23456 │
│ ├─ Process 1 → localhost: │
│ │ 23456 │
│ ├─ Process 2 → localhost: │
│ │ 23456 │
│ └─ Process 3 → localhost: │
│ 23456 │
│ │
│ 所有通信在Executor内部! │
└──────────────────────────────┘
关键区别
Driver的Master vs DDP的Master
| 类别 | Spark Driver Master | DDP Master |
|---|---|---|
| 作用 | 管理Spark任务 | 协调DDP进程 |
| 地址 | Spark集群管理 | localhost |
| 端口 | Spark默认(7077) | 23456(我们指定) |
| 运行位置 | 集群的某个节点 | Executor内部 |
| 是否需要知道 | 不需要(Spark管理) | 需要(我们配置) |
网络通信
Spark通信(Driver ↔ Executor):
┌──────────┐ ┌──────────┐
│ Driver │ ←── Spark RPC ──→ │ Executor │
│ IP: X.X │ │ IP: Y.Y │
└──────────┘ └──────────┘
DDP通信(Executor内部的进程间):
┌───────────┐
│ Process 0 │
└────┬──────┘
│
┌────────────┼────────────┐
│ │ │
↓ ↓ ↓
┌───────────┐ ┌───────────┐
│ DDP Master│ ←─────────→│ Process 1 │
│ localhost │ └───────────┘
│ :23456 │ │
└───────────┘ │
│ │
└────────────┬────────────┘
│
┌───────────┐
│ Process 2 │
└───────────┘
│
┌───────────┐
│ Process 3 │
└───────────┘
总结
答案
master_addr和master_port是指Executor内部的DDP Master,与Driver无关!
具体说明
-
Spark Driver的Master
- ❌ 不是我们配置的
- ✅ 由Spark自动管理
- ✅ 我们不需要关心
-
DDP的Master(我们配置的)
- ✅ 运行在Executor内部
- ✅ 地址:localhost(Executor内部)
- ✅ 端口:23456(Executor内部)
- ✅ 用于DDP进程间通信
当前配置是正确的
python
'--master_addr', 'localhost', # ✅ Executor内部的地址
'--master_port', '23456', # ✅ Executor内部的端口
因为:
- 所有DDP进程在Executor内部
- 使用localhost通信(本地回环)
- 不需要知道Executor的外部IP
- 不需要知道Driver的IP
常见误解
❌ 误解1:master_addr应该填Executor的IP
python
# 错误理解
'--master_addr', '10.0.0.5', # Executor的IP
为什么错误:
- DDP进程在同一executor上
- 通过localhost通信即可
- 不需要外部IP
❌ 误解2:master_addr应该填Driver的IP
python
# 错误理解
'--master_addr', '192.168.1.100', # Driver的IP
为什么错误:
- Driver不参与DDP训练
- DDP的Master在Executor上运行
- 使用localhost即可
✅ 正确理解:使用localhost
python
# 正确配置
'--master_addr', 'localhost', # Executor内部的本地地址
为什么正确:
- 所有DDP进程在同一executor上
- 使用本地回环接口通信
- 简单且可靠
实际操作
查看配置的地方
-
spark_train_ddp_wrapper.py(在Executor上运行)
pythontorchrun_cmd = [ '--master_addr', 'localhost', # ← 这里 '--master_port', '23456', # ← 这里 ]✅ 这些配置用于Executor内部的DDP通信
-
spark_submit_hourly_ddp.sh(在本机运行)
bashspark-submit \ --master yarn \ # ← 这是Spark的Master --deploy-mode cluster \ spark_train_ddp_wrapper.py✅ 这是Spark的配置,与DDP无关
重要区别
| 配置 | 位置 | 作用 |
|---|---|---|
--master yarn |
spark-submit | Spark的Master |
--master_addr localhost |
torchrun | DDP的Master |
--master_port 23456 |
torchrun | DDP的Master端口 |
它们是两套独立的系统!