Skip to content

搞英语 → 看世界

翻译英文优质信息和名人推特

Menu
  • 首页
  • 作者列表
  • 独立博客
  • 专业媒体
  • 名人推特
  • 邮件列表
  • 关于本站
Menu

使用 thread_local 缓存加速 C++ 函数

Posted on 2025-10-20

在大型代码库中,我们经常会遇到一些令人不快的设计,这些设计会损害我们的性能。我们可能正在寻找一种非侵入式的方法来提升性能。例如,您可能不想更改函数签名。

让我们考虑一个具体的例子。也许有人设计了编程接口,让你必须使用索引来访问 map 中的值。他们可能有这样的代码:

“`cpp
自动 at_index(map_like auto&index_map,size_t idx){
size_t 计数 = 0;
对于(const auto&[键,值]:索引图)​​{
如果(count == idx)
返回值;
计数++;
}
抛出 std::out_of_range(“索引超出范围”);
}
“`

这段代码遍历了 map 中 `idx` 的键。通常,这意味着某种链表遍历。如果你坚持使用这个接口,遍历值可能意味着重复调用 `at_index` 函数:

“`cpp
for (size_t i = 0; i < input_size; ++i) { at_index(index_map, i); } “` 如果您学过计算机科学,就会立即发现问题:我的代码具有二次复杂度。如果将地图大小加倍,则运行时间可能会翻两番。如果地图中有 2 或 4 个元素,则可能没问题,但如果有 400 个元素,则肯定不行。正确的解决方案是避免这样的设计。如果可以直接访问地图,则可以直接对其进行迭代:“`cpp for (auto& [key, value] : index_map) { sum += value; } “` 但是如果您遇到困难怎么办?那么您可以使用静态或 `thread_local` 缓存。关键在于将地图中的位置保存在缓存中,并从那里开始下一个查询。如果用户通常按顺序查询,那么您的缓存应该会极大地加快功能速度。 “`cpp auto at_index_thread_local_cache(map_like auto& index_map, size_t idx) { using iterator = decltype(index_map.begin()); struct Cache { iterator last_iterator; size_t last_index = -1; }; thread_local Cache cache; if (idx == cache.last_index + 1 && cache.last_iterator != index_map.end()) { cache.last_iterator++; cache.last_index = idx; if (cache.last_iterator != index_map.end()) { return cache.last_iterator->second;
} 别的 {
抛出 std::out_of_range(“索引超出范围”);
}
} 别的 {
缓存.last_iterator = index_map.begin();
缓存.last_index = -1;
size_t 计数 = 0;
对于(自动它=index_map.begin();
它!= index_map.end();++它){
如果(count == idx){
缓存.last_iterator = 它;
缓存.last_index = idx;
返回它->第二;
}
计数++;
}
抛出 std::out_of_range(“索引超出范围”);
}
}
“`

在 C++ 中,“thread_local”变量是指在同一线程中只有一个该变量的实例(由所有函数调用共享)。如果您希望整个程序只有一个该变量的实例,可以使用“static”,但在本例中,“thread_local”是最佳选择。您可能担心“thread_local”变量的性能影响,但它通常非常便宜:访问或修改它时,我们只需添加几条指令。

我们的缓存变量会记住每个线程上次访问的迭代器和索引。如果请求下一个索引,我们只需递增迭代器并返回。如果访问是非顺序的或第一次调用,它会从头开始回退到线性扫描,并在此过程中重建缓存。

代码更复杂,如果您不按顺序访问键,速度可能会更慢。然而,性能提升可能是巨大的。[我编写了一个基准测试程序,使用包含 400 个元素的 Map 进行测试](https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/tree/master/2025/10/19/)。

| 方法 | ns/key | 说明/key |
| ——– | ——– | ——– |
| 原版 | 300 | 2000 |
| 缓存 | 2 | 17 |

就我而言,缓存使性能提高了 150 倍。还不错。

原文: https://lemire.me/blog/2025/10/19/speeding-up-c-functions-with-a-thread_local-cache/

本站文章系自动翻译,站长会周期检查,如果有不当内容,请点此留言,非常感谢。
  • Abhinav
  • Abigail Pain
  • Adam Fortuna
  • Alberto Gallego
  • Alex Wlchan
  • Anil Dash
  • Answer.AI
  • Arne Bahlo
  • Ben Carlson
  • Ben Kuhn
  • Bert Hubert
  • Big Technology
  • Bits about Money
  • Brandon Skerritt
  • Brian Krebs
  • ByteByteGo
  • Chip Huyen
  • Chips and Cheese
  • Christopher Butler
  • Colin Percival
  • Cool Infographics
  • Dan Sinker
  • David Walsh
  • Dmitry Dolzhenko
  • Dustin Curtis
  • eighty twenty
  • Elad Gil
  • Ellie Huxtable
  • Ethan Dalool
  • Ethan Marcotte
  • Exponential View
  • FAIL Blog
  • Founder Weekly
  • Geoffrey Huntley
  • Geoffrey Litt
  • Greg Mankiw
  • HeardThat Blog
  • Henrique Dias
  • Herman Martinus
  • Hypercritical
  • IEEE Spectrum
  • Investment Talk
  • Jaz
  • Jeff Geerling
  • Jonas Hietala
  • Josh Comeau
  • Lenny Rachitsky
  • Li Haoyi
  • Liz Danzico
  • Lou Plummer
  • Luke Wroblewski
  • Maggie Appleton
  • Matt Baer
  • Matt Stoller
  • Matthias Endler
  • Mert Bulan
  • Mind Matters
  • Mostly metrics
  • Naval Ravikant
  • News Letter
  • NextDraft
  • Non_Interactive
  • Not Boring
  • One Useful Thing
  • Phil Eaton
  • Product Market Fit
  • Readwise
  • ReedyBear
  • Robert Heaton
  • Rohit Patel
  • Ruben Schade
  • Sage Economics
  • Sam Altman
  • Sam Rose
  • selfh.st
  • Shtetl-Optimized
  • Simon schreibt
  • Slashdot
  • Small Good Things
  • Steph Ango
  • Stephen Wolfram
  • Steve Blank
  • Taylor Troesh
  • Telegram Blog
  • The Macro Compass
  • The Pomp Letter
  • thesephist
  • Thinking Deep & Wide
  • Tim Kellogg
  • Understanding AI
  • Wes Kao
  • 英文媒体
  • 英文推特
  • 英文独立博客
©2025 搞英语 → 看世界 | Design: Newspaperly WordPress Theme