使用Apache Beam执行DLRM预处理时,增加direct_num_workers性能反而下降
DLRM预处理本地Beam性能问题解析
核心现象
使用Apache Beam执行DLRM预处理时,本地DirectRunner运行单个Criteo Kaggle子文件,direct_num_workers设置越高,性能反而越差:
- AMD EPYC 7313(16核):1线程65秒 → 8线程159秒 → 16线程357秒
- Intel Xeon Gold 6248:1线程93秒 → 8线程318秒 → 16线程626秒
是不是必须用Google Cloud Dataflow?
不是必须。DirectRunner是为本地调试、小规模任务设计的,只是它的并行机制和分布式运行时(如Dataflow)差异大,单文件场景下未必能发挥多线程优势,但多文件批量处理时,Dataflow的分布式调度能真正利用并行能力。
性能反向下降的关键原因
1. 磁盘IO竞争(最核心)
单个子文件的读取是单源串行IO:
- 机械硬盘:多线程读取同一文件会导致磁头频繁切换,大幅降低读取效率
- SSD:单文件顺序读取本身是串行优化的,多线程并行读取不会提速,反而增加线程调度开销
这种情况下,多线程不仅无法提升IO速度,还会因为资源内耗拖慢整体流程。
2. DirectRunner的调度开销
DirectRunner多线程模式下,每个worker需要处理任务拆分、序列化/反序列化、线程间通信等额外开销。当任务以IO为主、计算量不大时,这些开销会超过并行带来的收益,甚至拖慢整体。另外,单文件可能无法被Beam Source有效拆分为多个并行分片,导致多线程空转等待。
3. 预处理逻辑的串行依赖
如果DLRM预处理代码中存在全局锁、共享资源竞争,或者部分步骤必须串行执行(比如全局统计、批次依赖前序结果),多线程会因为锁等待进一步降低效率。
可行优化手段
1. 单文件场景优化
- 直接设置
direct_num_workers=1,避免IO竞争和调度开销,这是单文件任务的最优选择 - 将文件放入内存盘(如Linux的tmpfs),规避磁盘IO瓶颈,测试纯计算阶段的并行潜力
2. 多文件批量处理优化
- 同时处理多个子文件,让每个worker负责不同的文件,真正利用并行IO能力
- 尝试切换
direct_running_mode=multi_process,进程隔离可减少线程间锁竞争,更适合多文件并行
3. 代码与配置调优
- 检查预处理逻辑,移除全局共享资源的竞争点(如全局计数器、未加锁的共享变量)
- 调整Beam的分片策略,确保文件能被拆分为多个可并行处理的块(依赖Source支持)
- 关闭不必要的日志输出,减少额外IO开销
4. 何时切换到Dataflow
当需要处理全部512个子文件时,Dataflow的分布式调度能让每个节点独立处理不同文件,充分发挥集群并行优势。DirectRunner仅适合单文件逻辑调试,不适合大规模并行任务。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

