惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
Google DeepMind News
Google DeepMind News
J
Java Code Geeks
S
SegmentFault 最新的问题
Martin Fowler
Martin Fowler
罗磊的独立博客
T
The Blog of Author Tim Ferriss
N
Netflix TechBlog - Medium
大猫的无限游戏
大猫的无限游戏
Hugging Face - Blog
Hugging Face - Blog
Last Week in AI
Last Week in AI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Heimdal Security Blog
N
News and Events Feed by Topic
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy International News Feed
T
Tailwind CSS Blog
AWS News Blog
AWS News Blog
雷峰网
雷峰网
PCI Perspectives
PCI Perspectives
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
IT之家
IT之家
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Register - Security
The Register - Security
N
News | PayPal Newsroom
C
CERT Recently Published Vulnerability Notes
Microsoft Security Blog
Microsoft Security Blog
Attack and Defense Labs
Attack and Defense Labs
T
Tenable Blog
博客园 - 【当耐特】
Vercel News
Vercel News
GbyAI
GbyAI
博客园 - 司徒正美
量子位
T
Threat Research - Cisco Blogs
The Cloudflare Blog
The Last Watchdog
The Last Watchdog
MyScale Blog
MyScale Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Hacker News - Newest:
Hacker News - Newest: "LLM"
TaoSecurity Blog
TaoSecurity Blog
T
Troy Hunt's Blog
Y
Y Combinator Blog
P
Proofpoint News Feed
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Jina AI
Jina AI
Recent Commits to openclaw:main
Recent Commits to openclaw:main
月光博客
月光博客
Apple Machine Learning Research
Apple Machine Learning Research

StudyingLover's Blog

Diffusion Policy笔记 rwkv笔记 act笔记 nanovllm-block_manager opencode多智能体 nanobot-rl nanobot-sft nanobot-checkpoint_manager nanobot-gpt nanobot-mid-train Vision Mamba (Vim)笔记 BPE演示 最后一遍学习Transformer YOLOv5 目标检测笔记 下载根服务器解析记录 Dynaseal A Backend-Controlled LLM API Key Distribution Scheme with Constrained Invocation Parameters 判断链表有环 王道25数据结构勘误 关于perplexity的open-sourcing-r1-1776 AI为什么不像人类一样进行多轮对话 新博客改造日记和功能测试 linuxqq只显示登陆背景图 数字设计和计算机体系结构(机械工业出版社)勘误(自制) Dynaseal:面向未来端侧llm agent的llm api key分发机制 A Definitive Guide to Markdown Style This post is using MDX, Where you can embed JSX and Astro components RT-Patch学习 pydantic实现的LLM ReAct fastapi 和 uvicorn 设置监听 ipv6 pydantic+openai+json 控制大模型输出的最佳范式 解决 Matplotlib Scatter 不支持 Marker 列表的问题:mscatter 实现 roofline model zhipuAI接口兼容openai 在docker部署fastapi宝塔里使用nginx反代套上cloudflare获取请求的真实ip clion搭建libbpf-bootstrap开发环境 coze+coze-discord-proxy+ChatNextWebUI实现AI自由 安卓内核时间使用的是UTC时间 colab运行google最新开源模型Gemma Sora技术报告 视频生成模型作为世界模拟器 笔记 archlinux flutter开发踩坑 fastapi集成google auth登录 linux下NTFS磁盘报错输入输出错误 Venn-Abers 预测器 基于Venn-Abers预测器的系统日志异常检测方法_顾兆军 手机平板远程访问kvm虚拟机的windows phi-2弱智吧测评 poe的gemini pro或是百度开发 google gemini api使用 google gemini api申请 构建用于复杂数据处理的高效UDP服务器和客户端 matplotlib中文字体渲染 TruFor笔记和代码复现 深入分析:GitHub Trending 项目 "multipleWindow3dScene" pua大模型 ggml教程|mnist手写体识别量化推理 xgboost2.0最佳实践 xgboost使用GPU最佳实践 马踏棋盘 cloudlflare推理llama2 docker搭建elasticsearch并使用python连接 FreeU-文字生成图片的免费午餐笔记 使用xgboost的c接口推理模型 Archlinux使用CMake调用xgboost的c接口 m2cgen生成机器学习c语言推理代码 xgboost模型序列化存储并推理 speculative-sampling笔记 prompt2model笔记 RoboTAP笔记 自建obsidian同步服务 MediaPipe即将推出图像生成服务 Dual-Stream Diffusion Net for Text-to-Video Generation笔记 ViT在DDPM取代UNet(DiT) arch4edu搞崩了我的flutter LISA(推理分割)笔记 在终端绘制GPU显存使用曲线 GPTBot介绍 arch蓝牙无法连接 GPU部署llama-cpp-python(llama.cpp通用) 花式求GCD 使用llama构建一个蜜罐(前端) 使用llama构建一个蜜罐(后端) llama-cpp-python快速上手 快速上手llama2.c(更新版) Paper Gestalt笔记 DINO-v2笔记 快速上手llama2.c AnyDoor笔记 Archlinux安装scrcpy加载共享库出错 error while loading shared libraries:libusb-1.0.so.0:wrong ELF class:ELFCLASS32 npc_gzip笔记 python调用c++函数 Filesystem type ntfs3,ntfs not configured in kernel open_clip编码图像和文本 PicGo配置CloudflareR2图片储存 ArchlinuxGnome快捷键打开终端 clip-interrogator代码解析 GroundingDINO安装报错解决 2023华为鲲鹏畅想日暨西安高新国际会议中心零食午饭测评 RoboMaster开源仓库汇总(长期更新) 没有手都可以在腾讯云创建镜像 I3D笔记
nanobot-pre-train
About the Author StudyingLover · 2026-01-18 · via StudyingLover's Blog

数据构造

  • 每行都从 [<|bos|>]token开始
  • 每条数据(row)100% token利用率(无padding)

具体做法:

先使用Tokenizer给每个文档前自动添加 <|bos|> token,然后初始化一个row = [],大小2049。假设buffer中有文档: 500 tokens, 800 tokens, 1200 tokens, 2500 tokens, remaining = 2049

  1. 选最大的能放入的: 1200 tokens
    • row = [doc1200] 1200 tokens
    • remaining = 849
  2. 再选最大的: 800 tokens
    • row = doc1200, doc800]
    • remaining = 49
  3. 没有文档 ≤49, 裁剪最短的文档(500 tokens)
    • row = [doc1200, doc800, doc500[:49]]
    • 结束

不难发现,单个row中会存在多个BOS,这能让AI学会处理文档边界和上下文切换

实践经验

Meta张量初始化(节省显存)

with torch.device("meta"):
    model = GPT(config)  # 只有shape没有数据
model.to_empty(device=device)  # 分配存储但不初始化
model.init_weights()  # 最后才初始化

数据预取(Pipeline优化)

正常的非优化写法是在每个micro_step开始时取数据:

for micro_step in range(grad_accum_steps):
    x, y, state = next(train_loader)  # ← 先取数据(GPU空闲等待)
    loss = model(x, y)                 # 然后前向
    loss.backward()                    # 然后反向

这就存在问题,取数据时GPU闲置,等待CPU的I/O操作

这里的优化写法是

x, y, state = next(train_loader)  # 循环前取第一批

for micro_step in range(grad_accum_steps):
    loss = model(x, y)                 # 前向(GPU忙)
    loss.backward()                    # 反向(GPU忙)
    x, y, state = next(train_loader)   # ← GPU计算时CPU异步准备下一批

GPU计算当前batch的同时,CPU可以并行地tokenize/加载下一批数据,隐藏I/O延迟,提高硬件利用率。

有人会有问题

  • loss.backward() 还没算完,x, y, state = next(train_loader) 会执行吗
  • 那会不会loss.backward() 还没算完,代码已经跑到最后了

loss.backward() 会异步启动GPU上的反向传播,但不会阻塞CPU,所以说下一行会正常执行。但是,会有三部分同步cpu和gpu

  • loss = model(x, y)新的前向传播需要GPU资源,PyTorch会自动等待之前的kernel执行完毕
  • opt.step() 更新参数需要梯度,会等待所有backward完成
  • synchronize() 显式同步,这里的synchronize()是这样实现的synchronize = torch.cuda.synchronize if device_type == "cuda" else lambda: None

MFU(模型FLOPs利用率)监控

MFU (Model FLOPs Utilization) 是衡量GPU硬件利用效率的关键指标。

  • MFU = 50%:你充分利用了GPU理论算力的一半,非常优秀(Transformer训练通常30-50%)
  • MFU = 20%:一般水平,有优化空间
  • MFU = 5%:很差,可能有严重瓶颈(数据加载慢、显存不足、kernel效率低)
  • 为什么达不到100%?
  1. 内存带宽瓶颈:读写数据耗时
  2. 非计算操作:LayerNorm、激活函数等
  3. 通信开销:DDP的AllReduce
  4. Kernel启动开销:小操作的固定成本
  5. 空闲等待:数据加载、同步等
num_flops_per_token = model.estimate_flops()
flops_per_sec = num_flops_per_token * batch_size / dt
total_peak = gpu_peak_flops * ddp_world_size
mfu = 100 * flops_per_sec / total_peak
  • num_flops_per_token: 处理一个token需要的浮点运算数(前向+反向)
  • batch_size: 一次处理多少个token
  • dt: 实际耗时(秒)
  • gpu_peak_flops: 单张GPU的理论峰值(BF16)

那怎么得到gpu_peak_flops呢?查表

# hardcoded BF16 peak flops for various GPUs
# inspired by torchtitan: https://github.com/pytorch/torchtitan/blob/main/torchtitan/tools/utils.py
# and PR: https://github.com/karpathy/nanochat/pull/147
def get_peak_flops(device_name: str) -> float:
    name = device_name.lower()

    # --- NVIDIA Blackwell ---
    if "gb200" in name or "grace blackwell" in name:
        return 2.5e15
    if "b200" in name:
        return 2.25e15
    if "b100" in name:
        return 1.8e15

    # --- NVIDIA Hopper (H100/H200/H800) ---
    if "h200" in name:
        if "nvl" in name or "pcie" in name:
            return 836e12
        return 989e12  # H200 SXM
    if "h100" in name:
        if "nvl" in name:
            return 835e12
        if "pcie" in name:
            return 756e12
        return 989e12  # H100 SXM
    if "h800" in name:
        if "nvl" in name:
            return 989e12
        return 756e12  # H800 PCIe

    # --- NVIDIA Ampere data center ---
    if "a100" in name or "a800" in name:
        return 312e12
    if "a40" in name:
        return 149.7e12
    if "a30" in name:
        return 165e12

    # --- NVIDIA Ada data center ---
    if "l40s" in name or "l40-s" in name or "l40 s" in name:
        return 362e12
    if "l4" in name:
        return 121e12

    # --- AMD CDNA accelerators ---
    if "mi355" in name:
        return 2.5e15
    if "mi325" in name or "mi300x" in name:
        return 1.3074e15
    if "mi300a" in name:
        return 980.6e12
    if "mi250x" in name:
        return 383e12
    if "mi250" in name:
        return 362.1e12

    # --- Intel ---
    if "data center gpu max 1550" in name:
        # Ponte Vecchio (PVC) - dynamic based on compute units
        max_comp_units = torch.xpu.get_device_properties("xpu").max_compute_units
        return 512 * max_comp_units * 1300 * 10**6

    # --- Consumer RTX (for hobbyists) ---
    if "5090" in name:
        return 209.5e12
    if "4090" in name:
        return 165.2e12
    if "3090" in name:
        return 71e12

    # Unknown GPU - return inf so MFU shows as 0% rather than a wrong guess
    logger.warning(f"Peak flops undefined for: {device_name}, MFU will show as 0%")
    return float('inf')