multithreading - thread_local 会有什么性能损失?
问题描述
使用 C++11 和/或 C11 thread_local
,我们是否应该预期thread_local
在 x86(32 位或 64 位)Linux、Red Hat 5 或更新版本以及最近的 g++/gcc(例如,版本 4 或较新的)还是叮当声?
解决方案
在带有 gcc-8.3 (options) 的 Ubuntu 18.04 x86_64 上-pthread -m{arch,tune}=native -std=gnu++17 -g -O3 -ffast-math -falign-{functions,loops}=64 -DNDEBUG
,差异几乎是难以察觉的:
#include <benchmark/benchmark.h>
struct A { static unsigned n; };
unsigned A::n = 0;
struct B { static thread_local unsigned n; };
thread_local unsigned B::n = 0;
template<class T>
void bm(benchmark::State& state) {
for(auto _ : state)
benchmark::DoNotOptimize(++T::n);
}
BENCHMARK_TEMPLATE(bm, A);
BENCHMARK_TEMPLATE(bm, B);
BENCHMARK_MAIN();
结果:
Run on (16 X 5000 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x8)
L1 Instruction 32 KiB (x8)
L2 Unified 256 KiB (x8)
L3 Unified 16384 KiB (x1)
Load Average: 0.59, 0.49, 0.38
-----------------------------------------------------
Benchmark Time CPU Iterations
-----------------------------------------------------
bm<A> 1.09 ns 1.09 ns 642390002
bm<B> 1.09 ns 1.09 ns 633963210
在 x86_64thread_local
上,变量是相对于fs
寄存器访问的。具有这种寻址模式的指令通常要长 2 个字节,因此理论上它们可能会花费更多时间。
在其他平台上,这取决于如何thread_local
实现对变量的访问。有关更多详细信息,请参阅线程本地存储的 ELF 处理。
推荐阅读
- php - PHP Composer 全局配置私有存储库 URL 列表
- python - 合并两个 python 字典并在新更新的字典中保留最大键 val
- sql - 从静态日期计算日期
- mongodb - .find() 即使数据存在也不返回
- javascript - 使用循环和映射时更清晰的反应代码
- python - 如何从具有体育成绩的数据集中平均历史统计数据?
- oracle - 在选择列表中获取选定的文本并将其保存在会话中
- python - 复制具有特定日期的目录中的文件
- javascript - 删除项目后如何重新渲染数组列表?它给出一个错误并且不会重新渲染
- react-native-android - 无法在没有远程调试器的情况下在反应本机应用程序上调用 web3.eth.accounts.create()