gpt4 book ai didi

c++ - 为什么 std::none_of 比手动循环更快?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:39:52 25 4
gpt4 key购买 nike

我将 std::none_of 的性能与三种不同的手动实现进行了基准测试,使用 i) for 循环,ii) 基于范围的 for 循环和 iii) 迭代器。令我惊讶的是,我发现虽然所有三个手动实现花费的时间大致相同,但 std::none_of 明显更快。我的问题是 - 为什么会这样?

我使用了 Google 基准库并使用 -std=c++14 -O3 编译。运行测试时,我将进程的亲和性限制为单个处理器。我使用 GCC 6.2 得到以下结果:

Benchmark                  Time           CPU Iterations
--------------------------------------------------------
benchmarkSTL 28813 ns 28780 ns 24283
benchmarkManual 46203 ns 46191 ns 15063
benchmarkRange 48368 ns 48243 ns 16245
benchmarkIterator 44732 ns 44710 ns 15698

在 Clang 3.9 上,std::none_of 也比手动 for 循环更快,尽管速度差异较小。这是测试代码(为简洁起见,仅包括手册 for 循环):

#include <algorithm>
#include <array>
#include <benchmark/benchmark.h>
#include <functional>
#include <random>

const size_t N = 100000;
const unsigned value = 31415926;

template<size_t N>
std::array<unsigned, N> generateData() {
std::mt19937 randomEngine(0);
std::array<unsigned, N> data;
std::generate(data.begin(), data.end(), randomEngine);
return data;
}

void benchmarkSTL(benchmark::State & state) {
auto data = generateData<N>();
while (state.KeepRunning()) {
bool result = std::none_of(
data.begin(),
data.end(),
std::bind(std::equal_to<unsigned>(), std::placeholders::_1, value));
assert(result);
}
}

void benchmarkManual(benchmark::State & state) {
auto data = generateData<N>();
while (state.KeepRunning()) {
bool result = true;
for (size_t i = 0; i < N; i++) {
if (data[i] == value) {
result = false;
break;
}
}
assert(result);
}
}

BENCHMARK(benchmarkSTL);
BENCHMARK(benchmarkManual);

BENCHMARK_MAIN();

请注意,使用随机数生成器生成数据是无关紧要的。将第 i 元素设置为 i 并检查是否包含值 N + 1 时,我得到了相同的结果。

最佳答案

经过更多调查,我将尝试回答我自己的问题。正如 Kerrek SB 所建议的,我查看了生成的汇编代码。最重要的是,与其他三个版本相比,GCC 6.2 在展开 std::none_of 中隐含的循环方面做得更好。

海湾合作委员会 6.2:

  • std::none_of 展开 4 次 -> ~30µs
  • 手动 for、范围 for 和迭代器根本没有展开 -> ~45µs

正如 Corristo 所建议的,结果取决于编译器 - 这非常有道理。 Clang 3.9 展开了除范围 for 循环之外的所有内容,尽管程度不同。

clang 3.9

  • `std::none_of' 展开 8 次 -> ~30µs
  • 手动 for 展开 5 次 -> ~35µs
  • range for 根本没有展开 -> ~60µs
  • 迭代器展开 8 次 -> ~28µs

所有代码均使用 -std=c++14 -O3 编译。

关于c++ - 为什么 std::none_of 比手动循环更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39819745/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com