首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >noexcept能提高性能吗?

noexcept能提高性能吗?
EN

Stack Overflow用户
提问于 2013-04-19 19:55:32
回答 3查看 9.1K关注 0票数 32

noexcept函数说明符是否旨在提高性能,因为生成的对象中可能没有异常的记账代码,因此应该尽可能将其添加到函数声明和定义中?我首先想到的是可调用对象的包装器,尽管检查表达式可能会使源代码“膨胀”,但noexcept可以起到一定的作用。这样做值得吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-04-19 20:45:56

顶级编译器生成已经优化的代码,就像不能抛出的代码一样,然后异常发生时的情况由异常处理机制通过查看与函数相关的元数据找到的行外代码来处理。不过,我认为在已知不需要它的情况下,省略它在代码大小上有一些好处。

可能在某些情况下,nothrow规范确实允许某些特定的优化:

代码语言:javascript
复制
int main() {
    int i = 0;
    try {
        ++i;
        thing_that_cannot_throw();
        ++i;
        thing_that_can_throw();
        ++i;
    } catch (...) {}
    std::cout << i << "\n";
}

在这里,第二个++i在理论上可以在调用thing_that_cannot_throw之前重新排序( i只是初始化为2)。然而,它是否在实践中是另一回事,因为在调试器或函数调用之上的堆栈中保证变量状态的实现会希望i在调用期间具有值1,即使它是任何标准方法都无法观察到的局部变量。

我怀疑nothrow保证对程序员比对编译器更有价值。如果你正在编写提供强异常保证的代码,那么通常你会执行某些关键操作,你需要提供nothrow保证(交换、移动和析构函数是常见的候选)。

票数 14
EN

Stack Overflow用户

发布于 2013-04-20 00:43:48

从理论上讲,noexcept将提高性能。但从另一方面来说,这也可能会带来一些问题。

在大多数情况下,it不应该被指定为,因为优点太少而无法考虑,而且这可能会使代码升级变得痛苦。Andrzej撰写的This post详细介绍了原因。

如果它太长了,就接受我从中总结出来的这些建议:

  1. noexcept批注函数如果
    • 它们已经被throw()批注了,
    • 或者它们是很好的候选者(在post中列出),并且永远不会肯定地抛出,
    • 或者它们是移动构造函数,其noexcept批注不能被编译器正确推导的移动赋值,并且它们的实例应该被放入一些STL代码中

  1. 如果您真的担心性能降低、
  2. 或调用std::terminate
  3. 的风险,或者您只是不确定新功能、
  4. ,或者您不确定应该将函数设置为noexcept或not.

,则不要使用D31注释函数

票数 17
EN

Stack Overflow用户

发布于 2020-12-18 02:52:09

我偶然发现了一个“真实世界”的例子,在这个例子中,没有例外会有不同之处。我想在这里分享它,因为它可能会帮助其他人形成观点。

首先介绍一些背景知识:标准库容器尽量做到“异常安全”。这意味着在异常被引发(并被捕获)后,它们会为容器的状态提供一定的保证。std::vector::emplace_back就是一个很好的例子。如果由于某种原因插入失败,emplace_back会保证向量看起来没有改变。请参阅emplace_back上的cppreference。然而,当矢量需要重新定位以响应emplace时,这就变得有趣了。重新定位预先存在的向量项的最快方法(希望)是将它们move到新的放大缓冲区。不幸的是,move-construction可能会引发异常,因此如果值类型的move-ctor不是异常安全的,emplace_back需要求助于复制操作。但是,由于可以在编译时探测一个类型的move-noexept'ness,如果这被证明是合法的,std::vector仍然会采用更快的方法。

我收集了以下google基准来在本地进行测试:

代码语言:javascript
复制
#include "benchmark/benchmark.h"

#include <vector>

// This type really benefits from being moved instead of being copied
struct SlowCopy {
  SlowCopy(const size_t theSize) {
    for (int i = 0; i < theSize; ++i)
      itsData.emplace_back(i);
  }
  SlowCopy(const SlowCopy &) = default;
  SlowCopy(SlowCopy &&) noexcept = default;

  std::vector<int> itsData;
};

// The template parameter specifies whether the move constructor is noexcept or not
template<bool YesNo>
struct MovableNoexcept {
  MovableNoexcept(const size_t theSize) : itsData{theSize} {}
  MovableNoexcept(const MovableNoexcept &) = default;
  MovableNoexcept(MovableNoexcept &&) noexcept(YesNo) = default;
  MovableNoexcept& operator=(const MovableNoexcept &)  = default;
  MovableNoexcept& operator=(MovableNoexcept &&) noexcept(false) = default;
  SlowCopy itsData;
};

// This benchmark takes 2 arguments:
// 1. How many items do we push into a vector
// 2. How big are the items that are in the vector
template<bool IsNoexcept>
static void BM_MoveRelocateNoexcept(benchmark::State& state) {
  std::vector<MovableNoexcept<IsNoexcept>> aExcepts;
  for (auto _ : state) {
    for (int i = 0; i < state.range(0); ++i)
      aExcepts.emplace_back(state.range(1));
    benchmark::ClobberMemory();
  }
}

// Test 1k elements @ 64*sizeof(int) kb
BENCHMARK_TEMPLATE(BM_MoveRelocateNoexcept, false)->Args({1000, 1 << 16})->Repetitions(20);
BENCHMARK_TEMPLATE(BM_MoveRelocateNoexcept, true)->Args({1000, 1 << 16})->Repetitions(20);

// Test 100 elements @ 512*sizeof(int) kb
BENCHMARK_TEMPLATE(BM_MoveRelocateNoexcept, false)->Args({100, 1 << 19})->Repetitions(20);
BENCHMARK_TEMPLATE(BM_MoveRelocateNoexcept, true)->Args({100, 1 << 19})->Repetitions(20);

// Run the benchmark
BENCHMARK_MAIN();

在我的本地系统上,我测量了运行基准测试的以下结果:

代码语言:javascript
复制
Running ./noexcept_bench
Run on (8 X 4400 MHz CPU s)
CPU Caches:
  L1 Data 32 KiB (x4)
  L1 Instruction 32 KiB (x4)
  L2 Unified 256 KiB (x4)
  L3 Unified 8192 KiB (x1)
Load Average: 0.58, 0.70, 0.69
------------------------------------------------------------------------------------------------------
Benchmark                                                            Time             CPU   Iterations
------------------------------------------------------------------------------------------------------
BM_MoveRelocateNoexcept<false>/1000/65536/repeats:20_mean    157793886 ns    157556651 ns           20
BM_MoveRelocateNoexcept<false>/1000/65536/repeats:20_median  157752118 ns    157511285 ns           20
BM_MoveRelocateNoexcept<false>/1000/65536/repeats:20_stddev     294024 ns       292420 ns           20
BM_MoveRelocateNoexcept<true>/1000/65536/repeats:20_mean     119320642 ns    119235176 ns           20
BM_MoveRelocateNoexcept<true>/1000/65536/repeats:20_median   119256119 ns    119187012 ns           20
BM_MoveRelocateNoexcept<true>/1000/65536/repeats:20_stddev      190923 ns       180183 ns           20
BM_MoveRelocateNoexcept<false>/100/524288/repeats:20_mean    127031806 ns    126834505 ns           20
BM_MoveRelocateNoexcept<false>/100/524288/repeats:20_median  126939978 ns    126741072 ns           20
BM_MoveRelocateNoexcept<false>/100/524288/repeats:20_stddev     381682 ns       380187 ns           20
BM_MoveRelocateNoexcept<true>/100/524288/repeats:20_mean      95281309 ns     95175234 ns           20
BM_MoveRelocateNoexcept<true>/100/524288/repeats:20_median    95267762 ns     95152072 ns           20
BM_MoveRelocateNoexcept<true>/100/524288/repeats:20_stddev      176838 ns       176834 ns           20

查看这些结果,在两个基准测试中,非异常移动的测试相对于非异常移动的测试,加速比约为1.3

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16104057

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档