单机并行 #

并行策略概述 #

LightGBM 支持多种并行策略来加速训练:

text
┌─────────────────────────────────────────────────────────────┐
│                    LightGBM 并行策略                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 特征并行 (Feature Parallel)                             │
│     - 不同线程处理不同特征                                   │
│     - 适合特征数量大的场景                                   │
│                                                             │
│  2. 数据并行 (Data Parallel)                                │
│     - 不同线程处理不同数据分区                               │
│     - 适合数据量大的场景                                     │
│                                                             │
│  3. 投票并行 (Voting Parallel)                              │
│     - 减少通信开销的数据并行                                 │
│     - 适合分布式场景                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

多线程配置 #

基本配置 #

python
import lightgbm as lgb
import numpy as np
from sklearn.datasets import make_classification

X, y = make_classification(n_samples=10000, n_features=50, random_state=42)

params = {
    'objective': 'binary',
    'metric': 'auc',
    'num_leaves': 31,
    'num_threads': 4,
    'verbose': -1
}

train_data = lgb.Dataset(X, label=y)
model = lgb.train(params, train_data, num_boost_round=100)

print(f"使用线程数: {model.params.get('num_threads', 'auto')}")

自动线程数 #

python
params = {
    'objective': 'binary',
    'num_threads': -1,
    'verbose': -1
}

环境变量配置 #

python
import os

os.environ['OMP_NUM_THREADS'] = '4'

params = {
    'objective': 'binary',
    'verbose': -1
}

特征并行 #

原理 #

text
┌─────────────────────────────────────────────────────────────┐
│                    特征并行                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  数据 (所有样本)                                             │
│       │                                                      │
│       ▼                                                      │
│  ┌─────────┬─────────┬─────────┬─────────┐                 │
│  │线程1    │线程2    │线程3    │线程4    │                 │
│  │特征1-10 │特征11-20│特征21-30│特征31-40│                 │
│  └─────────┴─────────┴─────────┴─────────┘                 │
│       │         │         │         │                       │
│       ▼         ▼         ▼         ▼                       │
│  局部最优  局部最优  局部最优  局部最优                       │
│       │         │         │         │                       │
│       └─────────┴─────────┴─────────┘                       │
│                     │                                        │
│                     ▼                                        │
│               全局最优分裂                                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

使用特征并行 #

python
params = {
    'objective': 'binary',
    'metric': 'auc',
    'num_threads': 4,
    'feature_fraction': 0.8,
    'verbose': -1
}

数据并行 #

原理 #

text
┌─────────────────────────────────────────────────────────────┐
│                    数据并行                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────┬─────────┬─────────┬─────────┐                 │
│  │数据分区1│数据分区2│数据分区3│数据分区4│                 │
│  │样本1-250│样本251-500│样本501-750│样本751-1000│            │
│  └─────────┴─────────┴─────────┴─────────┘                 │
│       │         │         │         │                       │
│       ▼         ▼         ▼         ▼                       │
│  线程1     线程2     线程3     线程4                         │
│  本地直方图 本地直方图 本地直方图 本地直方图                  │
│       │         │         │         │                       │
│       └─────────┴─────────┴─────────┘                       │
│                     │                                        │
│                     ▼                                        │
│              全局直方图归约                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

使用数据并行 #

python
params = {
    'objective': 'binary',
    'metric': 'auc',
    'num_threads': 4,
    'verbose': -1
}

性能优化 #

线程数选择 #

python
import time
import matplotlib.pyplot as plt

def benchmark_threads(X, y, thread_counts=[1, 2, 4, 8, 16]):
    """测试不同线程数的性能"""
    times = []
    
    for n_threads in thread_counts:
        params = {
            'objective': 'binary',
            'num_threads': n_threads,
            'verbose': -1
        }
        
        train_data = lgb.Dataset(X, label=y)
        
        start = time.time()
        model = lgb.train(params, train_data, num_boost_round=100)
        elapsed = time.time() - start
        
        times.append(elapsed)
        print(f"线程数 {n_threads}: {elapsed:.2f}s")
    
    plt.figure(figsize=(10, 6))
    plt.plot(thread_counts, times, 'o-')
    plt.xlabel('线程数')
    plt.ylabel('训练时间 (s)')
    plt.title('线程数 vs 训练时间')
    plt.grid(True)
    plt.show()
    
    return times

X, y = make_classification(n_samples=50000, n_features=100, random_state=42)
times = benchmark_threads(X, y)

内存优化 #

python
params = {
    'objective': 'binary',
    'num_threads': 4,
    'max_bin': 127,
    'num_leaves': 31,
    'feature_fraction': 0.8,
    'bagging_fraction': 0.8,
    'verbose': -1
}

完整示例 #

python
import lightgbm as lgb
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
import time

X, y = make_classification(n_samples=50000, n_features=100, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

print("单线程训练:")
params_single = {
    'objective': 'binary',
    'metric': 'auc',
    'num_threads': 1,
    'verbose': -1
}

train_data = lgb.Dataset(X_train, label=y_train)
start = time.time()
model_single = lgb.train(params_single, train_data, num_boost_round=100)
single_time = time.time() - start
print(f"训练时间: {single_time:.2f}s")

print("\n多线程训练:")
params_multi = {
    'objective': 'binary',
    'metric': 'auc',
    'num_threads': 4,
    'verbose': -1
}

start = time.time()
model_multi = lgb.train(params_multi, train_data, num_boost_round=100)
multi_time = time.time() - start
print(f"训练时间: {multi_time:.2f}s")

print(f"\n加速比: {single_time / multi_time:.2f}x")

下一步 #

现在你已经掌握了 LightGBM 的单机并行,接下来学习 分布式训练,了解如何在多机环境下训练模型!

最后更新:2026-04-04