處理大數據集(Big Data for LLM Pre-training)是預訓練中最容易被忽視的瓶頸。如果直接用 JSON 或 CSV 格式讀取,兩張 RTX 5090 會花 80% 的時間在「等 CPU 讀硬碟」,這叫 I/O Bound。
1. 核心流程:從文本到二進制
預訓練不需要在訓練時動態 Tokenize,我們應該先處理好。
- 清洗 (Cleaning): 去重、去除低質量文本、過濾敏感詞。
- 分詞 (Tokenization): 使用你的 Tokenizer(如 Llama-3 Tokenizer)將文字轉成整數 ID。
- 封裝 (Packaging): 將這些 ID 存成
Uint16或Uint32的二進制文件。 - 內存映射 (Memory Mapping): 訓練時使用
mmap技術,直接從硬碟「映射」到內存,不需要一次性讀入整個文件。
2. 推薦工具:Hugging Face datasets
這是目前最高效且易用的工具。它底層使用 Apache Arrow 格式,支援超大數據集的流式處理。
步驟一:將原始數據轉為 Arrow 格式
假設有好幾百 GB 的 JSONL 文件:
</>Python
from datasets import load_dataset
# 1. 流式讀取原始數據(不佔內存)
raw_datasets = load_dataset("json", data_files="corpus/*.jsonl", split="train", streaming=False)
# 2. 定義 Tokenization 函數
def tokenize_function(examples):
return tokenizer(examples["text"], truncation=True, max_length=2048)
# 3. 映射處理並保存到硬碟(自動轉為二進制 Arrow 格式)
tokenized_datasets = raw_datasets.map(
tokenize_function,
batched=True,
num_proc=16, # 開啟多進程加速
remove_columns=["text"]
)
tokenized_datasets.save_to_disk("./my_pretrain_data")
3. 進階方案:Megatron-LM / TinyLlama 方式 (.bin + .idx)
如果你追求極致的讀取效能,業界常用 Memory-mapped (mmap) 格式。這種方式將數據存為一個巨大的 .bin 文件和一個索引 .idx 文件。
為什麼用 mmap?
- 零拷貝: 操作系統只在需要時才把硬碟數據加載到緩存。
- 隨機讀取: 在 1TB 的數據中隨機跳轉,延遲幾乎為零。
- 多進程安全: 多個訓練進程(Data Parallelism)可以同時讀取同一個文件而不會鎖死。
實作建議: 可以使用開源工具 Llama-Factory 或 lit-gpt 內建的預處理腳本。
4. 針對 2x 5090 的數據加載建議
- Prefetch Factor (預取因子): 在
DataLoader中設置prefetch_factor=2。這會讓 CPU 提前準備好下兩個 Batch,確保 GPU 算完一個後馬上能接到下一個。 - Pin Memory: 一定要設置
pin_memory=True。這能加快數據從系統 RAM 到 5090 顯存的傳輸速度。 - 硬碟選擇: 預訓練時,務必使用 NVMe SSD。如果是傳統機械硬碟(HDD),數據讀取速度(約 100MB/s)絕對跟不上兩張 5090 的運算速度(黑井架構運算極快)。
5. 數據集規模與訓練時間預估
對於 7B 模型,一個標準的「高質量」預訓練通常需要 1T 到 3T Tokens。


















