В среднем современный x64 процессор намного медленнее, чем его 64- или 32-битные аналоги? - PullRequest
1 голос
/ 15 марта 2020

Я полагаю, что Windows уже давно использует эту инструкцию для внутреннего использования, поэтому производители ЦП потратили бы усилия на оптимизацию?

Конечно, при условии надлежащим образом выровненной памяти и отсутствия совместного использования строка кэша et c.

1 Ответ

3 голосов
/ 15 марта 2020

Из любопытства я написал небольшой тест для сравнения стоимости 4- и 8-байтовых cmpxchg с cmpxchg16b:

#include <cstdint>
#include <benchmark/benchmark.h>

alignas(16) char input[16 * 1024] = {};

template<class T>
void do_benchmark(benchmark::State& state) {
    unsigned n = 0;
    T* p = reinterpret_cast<T*>(input);
    constexpr unsigned count = sizeof input / sizeof(T);
    unsigned i = 0;
    for(auto _ : state) {
        T v{0};
        n += __sync_bool_compare_and_swap(p + i++ % count, v, v);
    }
    benchmark::DoNotOptimize(n);
}

BENCHMARK_TEMPLATE(do_benchmark, std::int32_t);
BENCHMARK_TEMPLATE(do_benchmark, std::int64_t);
BENCHMARK_TEMPLATE(do_benchmark, __int128);
BENCHMARK_MAIN();

и запустил его на процессоре Coffee Lake i9-9900KS. .

Результаты с gcc-8.3.0:

$ make -rC ~/src/test -j8 BUILD=release run_cmpxchg16b_benchmark
g++ -o /home/max/src/test/release/gcc/cmpxchg16b_benchmark.o -c -pthread -march=native -std=gnu++17 -W{all,extra,error,no-{maybe-uninitialized,unused-function}} -g -fmessage-length=0 -O3 -mtune=native -ffast-math -falign-{functions,loops}=64 -DNDEBUG -mcx16 -MD -MP /home/max/src/test/cmpxchg16b_benchmark.cc
g++ -o /home/max/src/test/release/gcc/cmpxchg16b_benchmark -fuse-ld=gold -pthread -g /home/max/src/test/release/gcc/cmpxchg16b_benchmark.o -lrt /usr/local/lib/libbenchmark.a
sudo cpupower frequency-set --related --governor performance >/dev/null
/home/max/src/test/release/gcc/cmpxchg16b_benchmark
2020-03-15 20:18:48
Running /home/max/src/test/release/gcc/cmpxchg16b_benchmark
Run on (16 X 5100 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.43, 0.40, 0.34
---------------------------------------------------------------------
Benchmark                           Time             CPU   Iterations
---------------------------------------------------------------------
do_benchmark<std::int32_t>       3.53 ns         3.53 ns    198281069
do_benchmark<std::int64_t>       3.53 ns         3.53 ns    198256710
do_benchmark<__int128>           6.35 ns         6.35 ns    110215116

Результаты с clang-8.0.0:

$ make -rC ~/src/test -j8 BUILD=release TOOLSET=clang run_cmpxchg16b_benchmark
clang++ -o /home/max/src/test/release/clang/cmpxchg16b_benchmark.o -c -pthread -march=native -std=gnu++17 -W{all,extra,error,no-unused-function} -g -fmessage-length=0 -O3 -mtune=native -ffast-math -falign-functions=64 -DNDEBUG -mcx16 -MD -MP /home/max/src/test/cmpxchg16b_benchmark.cc
clang++ -o /home/max/src/test/release/clang/cmpxchg16b_benchmark -fuse-ld=gold -pthread -g /home/max/src/test/release/clang/cmpxchg16b_benchmark.o -lrt /usr/local/lib/libbenchmark.a
sudo cpupower frequency-set --related --governor performance >/dev/null
/home/max/src/test/release/clang/cmpxchg16b_benchmark
2020-03-15 20:19:00
Running /home/max/src/test/release/clang/cmpxchg16b_benchmark
Run on (16 X 5100 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.36, 0.39, 0.33
---------------------------------------------------------------------
Benchmark                           Time             CPU   Iterations
---------------------------------------------------------------------
do_benchmark<std::int32_t>       3.84 ns         3.84 ns    182461520
do_benchmark<std::int64_t>       3.84 ns         3.84 ns    182160259
do_benchmark<__int128>           5.99 ns         5.99 ns    116972653

Похоже, что cmpxchg16b примерно в 1,6-1,8 раза больше дороже 8 байт cmpxchg.

...