首页 > 解决方案 > thread_local 会有什么性能损失?

问题描述

使用 C++11 和/或 C11 thread_local,我们是否应该预期thread_local在 x86(32 位或 64 位)Linux、Red Hat 5 或更新版本以及最近的 g++/gcc(例如,版本 4 或较新的)还是叮当声?

标签: multithreadingc++11thread-local-storage

解决方案


在带有 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 处理。


推荐阅读