Less Slow C++
让 C++ 不那么慢:Less Slow C++
导航菜单
切换导航 登录
- 产品
- 解决方案 按公司规模
- 资源 主题
- 开源
- 企业
- 定价
搜索或跳转到...
搜索代码、仓库、用户、问题、拉取请求...
搜索 清除 搜索语法提示
提供反馈
我们会阅读每一条反馈,并非常认真地对待您的意见。 包括我的电子邮件地址,以便与我联系 取消 提交反馈
保存的搜索
使用保存的搜索可以更快地过滤结果
名称 查询 要查看所有可用的限定符,请参阅我们的文档。 取消 创建保存的搜索 登录 注册 重新聚焦 您已在另一个标签或窗口中登录。重新加载以刷新您的会话。您已在另一个标签或窗口中注销。重新加载以刷新您的会话。您已在另一个标签或窗口中切换了帐户。重新加载以刷新您的会话。关闭警报 {{ message }} ashvardanian / less_slow.cpp 公开
学习如何在 C++ 20、C 99、CUDA、PTX 和汇编中编写“Less Slow”的代码,从数值和 SIMD 到协程、ranges、异常处理、网络和用户空间 IO。 ashvardanian.com/tags/less-slow/
许可证
Apache-2.0 license 643 stars 36 forks Branches Tags Activity Star 通知 您必须登录才能更改通知设置
附加导航选项
ashvardanian/less_slow.cpp
文件夹和文件
名称| 名称| 最后提交消息| 最后提交日期 ---|---|---|---
最近提交
历史
374 Commits .github/workflows| .github/workflows .vscode| .vscode .clang-format| .clang-format .gitattributes| .gitattributes .gitignore| .gitignore CMakeLists.txt| CMakeLists.txt LICENSE| LICENSE README.md| README.md VERSION| VERSION less_slow.cpp| less_slow.cpp less_slow.cu| less_slow.cu less_slow_aarch64.S| less_slow_aarch64.S less_slow_amd64.S| less_slow_amd64.S less_slow_sm70.ptx| less_slow_sm70.ptx less_slow_sm80.ptx| less_slow_sm80.ptx less_slow_sm90a.ptx| less_slow_sm90a.ptx 查看所有文件
仓库文件导航
学习编写 Less Slow 的 C、C++ 和汇编代码
本仓库中的基准测试并不旨在完全涵盖每个主题,但它们有助于形成一种心态和直觉,以便进行面向性能的软件设计。它还提供了一个在 C++ 中使用一些非 STL 但事实上标准的库、通过 CMake 导入它们并从源代码编译的示例。对于更高级别的抽象和语言,请查看
less_slow.rs
和less_slow.py
。
许多现代代码都存在常见的缺陷,例如 bug、安全漏洞和性能瓶颈。大学课程经常教授过时的概念,而训练营则过度简化了关键的软件开发原则。
本仓库提供了编写高效 C 和 C++ 代码的实践示例。它利用了 C++20 功能,主要为 Linux 上的 GCC 和 Clang 编译器设计,但也可能在其他平台上工作。主题范围从在几纳秒内执行的基本微内核到涉及并行算法、协程和多态性的更复杂的结构。 一些亮点包括:
- 随机输入成本高 100 倍?! 了解输入生成有时比算法本身更耗费资源。
- 快 40 倍的三角函数: 仅用 3 行代码即可加速标准库函数,如
std::sin
。 - 使用自定义
std::ranges
和迭代器,惰性逻辑快 4 倍! - 超越
-O3
的编译器优化: 了解不那么明显的标志和技术,以实现 2 倍的加速。 - 矩阵乘法? 检查一下 3x3x3 GEMM 如何比 4x4x4 慢 70%,尽管操作数减少了 60%。
- 扩展 AI? 衡量理论 ALU 吞吐量和您的 BLAS 之间的差距。
- 多少个 if 条件算太多? 仅用 10 行代码测试 CPU 的分支预测器。
- 喜欢递归而不是迭代? 测量算法达到
SEGFAULT
的深度。 - 为什么要避免异常? 采用
std::error_code
或类似std::variant
的包装器? - 扩展到多个核心? 学习如何使用 OpenMP、Intel 的 oneTBB 或您的自定义线程池。
- 如何处理避免内存分配的 JSON? 使用 C++ 20 还是旧式的 C 99 工具更容易?
- 如何通过自定义键和透明比较器正确使用 STL 的关联容器?
- 如何通过
consteval
RegEx 引擎击败手写解析器? - 指针大小真的是 64 位吗? 以及如何利用指针标记?
- UDP 丢弃多少个数据包? 以及如何在用户空间通过
io_uring
提供 Web 请求? - Scatter 和 Gather 实现快 50% 的向量化不相交内存操作。
- Intel 的 oneAPI vs Nvidia 的 CCCL?
<thrust>
和<cub>
有什么特别之处? - CUDA C++、PTX 中间表示和 SASS,以及它们与 CPU 代码有何不同?
- 如何为性能关键型代码选择 intrinsics, inline
asm
和单独的.S
文件? - Tensor Cores & Memory 在 CPU 和 Volta、Ampere、Hopper 和 Blackwell GPU 上的差异!
- 编写 FPGA 代码与 GPU 有何不同,什么是 High-Level Synthesis, Verilog 和 VHDL? 🔜 #36
- 什么是加密 Enclaves,Intel SGX, AMD SEV 和 ARM Realm 的延迟是多少? 🔜 #31
要阅读,请跳转到 less_slow.cpp
源文件,并阅读代码片段和注释。 按照以下说明在您的环境中运行代码,并将其与阅读源代码时的注释进行比较。
运行基准测试
该项目旨在与 Linux、MacOS 和 Windows 上的 GCC、Clang 和 MSVC 编译器兼容。 也就是说,为了涵盖最广泛的功能,建议在 Linux 上使用 GCC:
- 如果您使用的是 Windows,建议您使用 WSL 设置 Linux 环境。
- 如果您使用的是 MacOS,请考虑使用来自 Homebrew 或 MacPorts 的 Clang 的非本机发行版。
- 如果您使用的是 Linux,请确保安装 CMake 和最新版本的 GCC 或 Clang 编译器以支持 C++20 功能。
如果您熟悉 C++ 并希望在阅读时查看代码和测量结果,您可以克隆仓库并执行以下命令。
git clone https://github.com/ashvardanian/less_slow.cpp.git # 克隆仓库
cd less_slow.cpp # 更改目录
pip install cmake --upgrade # PyPI 拥有较新版本的 CMake
sudo apt-get install -y build-essential g++ # 安装默认构建工具
sudo apt-get install -y pkg-config liburing-dev # 安装 liburing 以绕过内核
sudo apt-get install -y libopenblas-base # 安装数值库
cmake -B build_release -D CMAKE_BUILD_TYPE=Release # 生成构建文件
cmake --build build_release --config Release # 构建项目
build_release/less_slow # 运行基准测试
构建将从源代码中提取并编译多个第三方依赖项:
- Google 的 Benchmark 用于性能分析。
- Intel 的 oneTBB 用作 Parallel STL 后端。
- Meta 的 libunifex 用于 senders & executors。
- Eric Niebler 的 range-v3 替代
std::ranges
。 - Victor Zverovich 的 fmt 替代
std::format
。 - Ash Vardanian 的 StringZilla 替代
std::string
。 - Hana Dusíková 的 CTRE 替代
std::regex
。 - Niels Lohmann 的 json 用于 JSON 反序列化。
- Yaoyuan Guo 的 yyjson 用于更快的 JSON 处理。
- Google 的 Abseil 替代 STL 的关联容器。
- Lewis Baker 的 cppcoro 实现 C++20 协程。
- Jens Axboe 的 liburing 以简化 Linux 内核绕过。
- Chris Kohlhoff 的 ASIO 作为 networking TS 扩展。
- Nvidia 的 CCCL 用于 GPU 加速算法。
- Nvidia 的 CUTLASS 用于 GPU 加速线性代数。
要控制输出或运行特定的基准测试,请使用以下标志:
build_release/less_slow --benchmark_format=json # 以 JSON 格式输出
build_release/less_slow --benchmark_out=results.json # 将结果保存到文件而不是 `stdout`
build_release/less_slow --benchmark_filter=std_sort # 仅运行名称中包含 `std_sort` 的基准测试
为了提高稳定性和可重复性,请禁用 CPU 上的同步多线程 (SMT) 并使用 --benchmark_enable_random_interleaving=true
标志,该标志会像此处所述地对基准测试进行洗牌和交错。
build_release/less_slow --benchmark_enable_random_interleaving=true
Google Benchmark 通过 libpmf
支持 User-Requested Performance Counters。 请注意,收集这些可能需要 sudo
权限。
sudo build_release/less_slow --benchmark_enable_random_interleaving=true --benchmark_format=json --benchmark_perf_counters="CYCLES,INSTRUCTIONS"
或者,使用 Linux perf
工具来收集性能计数器:
sudo perf stat taskset 0xEFFFEFFFEFFFEFFFEFFFEFFFEFFFEFFF build_release/less_slow --benchmark_enable_random_interleaving=true --benchmark_filter=super_sort
项目结构
本仓库的主要文件显然是包含 CPU 端代码的 less_slow.cpp
C++ 文件。 创建了用于不同硬件特定优化的其他几个文件:
$ tree .
.
├── CMakeLists.txt # 所有文件的构建和汇编指令
├── less_slow.cpp # 主要 CPU 端基准测试代码,包含大部分示例
├── less_slow_amd64.S # 64 位 x86 CPU 的手写汇编内核
├── less_slow_aarch64.S # 64 位 Arm CPU 的手写汇编内核
├── less_slow.cu # 用于 Nvidia GPU 并行算法的 CUDA C++ 示例
├── less_slow_sm70.ptx # Nvidia Volta GPU 的手写 PTX IR 内核
└── less_slow_sm90a.ptx # Nvidia Hopper GPU 的手写 PTX IR 内核
梗图和参考文献
没有梗图的教育内容?! 算了吧!
Google Benchmark 功能
此基准测试套件使用 Google Benchmark 提供的大部分功能。 如果您编写了很多基准测试,并且避免阅读完整的用户指南,以下是最有用的功能的简要列表:
->Args({x, y})
- 将多个参数传递给参数化基准测试BENCHMARK()
- 注册一个基本基准测试函数BENCHMARK_CAPTURE()
- 使用不同的捕获值创建基准测试的变体Counter::kAvgThreads
- 指定线程平均计数器DoNotOptimize()
- 防止编译器优化掉操作ClobberMemory()
- 强制内存同步->Complexity(oNLogN)
- 指定和验证算法复杂度->SetComplexityN(n)
- 设置复杂度计算的输入大小->ComputeStatistics("max", ...)
- 计算跨运行的自定义统计信息->Iterations(n)
- 控制确切的迭代次数