构建9254修复了我的TG回归问题,并为NVIDIA GPU添加了PDL支持

Reddit r/LocalLLaMA 工具

摘要

llama.cpp的构建9254修复了一个token生成回归问题,并添加了对NVIDIA GPU的PDL(程序化依赖启动)支持,在新硬件上token生成速度提升高达10%。

在最近的几个构建中,我在mtp和非mtp模型上都遇到了TG回归问题,不得不回退到b9202。但刚运行了新的[b9254](https://github.com/ggml-org/llama.cpp/releases/tag/b9254),TG已恢复,并且在2x5060ti 16gb张量拆分上还额外获得了约5%的性能提升。我用PDL标志编译了cmake来试一下。我打算稍后不启用PDL进行对比测试,但目前在qwen3.6-35b-a3b-Q4_K_XL上得到了一致的结果:3.2k PP和127 tg/s。我并不是说我的结果都是PDL的功劳,但至少这个构建和b9202一样好甚至更好。时间会证明一切。 对话 # [**aendk**](https://github.com/aendk) 评论于[3周前](https://github.com/ggml-org/llama.cpp/pull/22522#issue-4351486947) # 概述 [程序化依赖启动](https://docs.nvidia.com/cuda/cuda-programming-guide/04-special-topics/programmatic-dependent-launch.html)(PDL)是一项针对较新NVIDIA GPU(CC >= 90;不包括Ada)的CUDA优化技术。它允许同一CUDA流中的CUDA内核重叠执行。与CUDA图类似,它减少了设备上的内核启动开销。两者的优势是相加的(PDL + CG > CG > PDL)。这一点可以通过Nsight Systems截图中单个CUDA流的可视化效果得到最佳体现;本应严格按顺序执行的内核现在并发运行。 PDL早在去年就曾在[#15479](https://github.com/ggml-org/llama.cpp/issues/15479)中提出。这个PR更好地集成了CUDA图语义,并且性能大幅提升。在RTX PRO 6000上,token生成阶段提速10%并不罕见;在DGX Spark上,我观察到了4-5%的改进(模型相关,详见下方详细统计数据)。 要充分发挥PDL的性能,内核需要配备两个新特性:同步屏障(`GGML_CUDA_PDL_SYNC`)和启动信号(`GGML_CUDA_PDL_LC`)。同步屏障限制内核执行,使其等待前一个内核写入的数据,从而避免竞态条件或过早的数据访问。启动信号指示当前内核在哪个点可以容忍下一个内核与其并行启动。此外,内核需要通过新的`ggml_cuda_kernel_launch()`函数启动。同步屏障可以通过仔细检查内核代码,识别内核输入的第一个“真正”数据访问(例如,排除指针算术)来放置。启动信号的放置需要一些手动调整和基准测试。 在这个草案PR中,我启用了`gpt-oss 20b`、`qwen3.5`和`nemotron 120B Super`中使用的所有内核。由于这些内核与其他模型共享,我还测试了更多模型。我几乎在所有模型的token生成阶段都观察到了加速,而预填充/上下文阶段基本上保持中性。 # 应用的启发式规则: * 在本草案中,对于同步屏障的放置,我假设每个内核的第一个“真正”数据访问是输入张量。如果存在前一个内核输出一个标量,而当前内核在`GGML_CUDA_PDL_SYNC`之前读取该标量的情况,则可能发生数据竞争。在标记为可合并之前,我会再次检查这一点。审查时请牢记。 * `GGML_CUDA_PDL_LC`的正确放置需要一些试错。在一些内核中,我在某些提交中注释掉了一些次优放置,这一点可见一斑。在某些内核中,放置`GGML_CUDA_PDL_LC`甚至会导致性能下降(最明显的是`mul_mat_vec_q`)。通常,信号在核函数中放置得越早,内核的延迟限制就越小,并且内核能承受的共享资源争用(由于后续内核的过早启动)就越多。 # 关于此实现的更多信息 * 即使图中的某些内核未启用PDL,此方法也可用。如果两个连续的内核已启用,它们将利用PDL(例如,许多模型中都存在启用了PDL的`quantize_q8`和`mul_mat_vec_q`)。 * 内核可以逐个启用。 * 优化`GGML_CUDA_PDL_LC`标志的放置需要一些试错,但针对一个模型的良好放置似乎对其他模型也有利。在内部测试中,我没有遇到过例如对模型A有利但对模型B性能更差的情况。 # 已知问题/待办事项 * 目前没有类似memcheck的工具来识别错误放置`GGML_CUDA_PDL_SYNC`情况下的竞态条件。 * 需要找到一种方法自动为不支持的(NVIDIA)GPU禁用PDL。简单地检查`GGML_CUDA_CC_HOPPER`不起作用。 * 更多内核可以迁移到PDL(不同的启动+同步屏障)。 * 需要移除已注释掉的启动信号实验代码。 * 与CUDA图本身一样,最初仅针对token生成推出此功能可能是有意义的。需要检查是否可行。 # 如何测试 你需要拥有较新的NVIDIA GPU(例如Blackwell),并使用`-D GGML_CUDA_PDL=ON`进行编译。 # 如何将其他内核加入PDL * 步骤1:使用`ggml_cuda_kernel_launch()`修改内核启动,并设置`GGML_CUDA_PDL_SYNC()`。修改内核启动而不设置同步屏障会导致竞态条件。 * 步骤2:迭代放置`GGML_CUDA_PDL_LC()`的位置。我采用的松散启发式方法是将其放在函数开头,测量性能,然后在内核中间的不同位置重复该过程。然后我选择了性能最好的放置位置。在我的测试中,将其放在内核底部附近几乎总是无效的。
查看原文

相似文章

Blackwell 与 PDL 性能提升

Reddit r/LocalLLaMA

Llama.cpp 现已支持适用于 Blackwell GPU 的 Nvidia 程序化依赖启动 (PDL),在 Token 生成时可带来 5-10% 的性能提升。该功能默认未启用,需通过编译标志开启。

MTP+GGML_CUDA_ENABLE_UNIFIED_MEMORY=1 - llama.cpp

Reddit r/LocalLLaMA

一位用户在 llama.cpp 上使用 GGML_CUDA_ENABLE_UNIFIED_MEMORY=1 标志对令牌生成速度进行基准测试,比较启用和未启用 MTP(多令牌预测)时的性能。结果显示,在 RTX5090 上使用 Qwen3.6-27B 模型时,启用 MTP 后速度从 49 tok/s 显著提升至 64 tok/s。