【问题标题】:C++20 constexpr std::copy optimizations for run-timeC++20 constexpr std::copy 运行时优化
【发布时间】:2019-12-27 18:15:53
【问题描述】:

cppreference.com 说:

在实践中,如果值类型是 TriviallyCopyable,则 std::copy 的实现会避免多次赋值并使用批量复制函数,例如 std::memmove

但是,该页面还指出,从 C++20 开始,不采用执行策略的重载将是 constexpr。标准会禁止这些运行时优化(因为 std::memmove 不是 constexpr)还是有办法针对运行时优化 constexpr 函数?

【问题讨论】:

    标签: c++ optimization constexpr c++20


    【解决方案1】:

    我们也可以吃蛋糕。

    我们只考虑copy 的最简单特化,即复制chars 的特化。在 C++17 中,这可能看起来像:

    char* copy(char const* first, char const* last, char* d)
    {
        memcpy(d, first, last - first);
        return d + (last - first);
    }
    

    当然,我们不能只拍constexpr,因为memcpy 不是一个constexpr 函数,那是行不通的。但它仅在持续评估期间不起作用。我们需要的是一种在运行时有条件地使用memcpy 的方法。

    我们在 C++20 中有这样的东西,std::is_constant_evaluated():

    constexpr char* copy(char const* first, char const* last, char* d)
    {
        if (std::is_constant_evaluated()) {
            while (first != last) {
                *d++ = *first++;
            }
            return d;       
        } else {
            memcpy(d, first, last - first);
            return d + (last - first);
        }
    }
    

    现在我们有了一个算法,它可以在运行时执行高效的操作,但在 constexpr 评估期间仍然有效。


    注意:它是if (std::is_constant_evaluated())从不 if constexpr (std::is_constant_evaluated())。后者相当于if constexpr (true) { ... }。 gcc 10.1 将开始警告这种错误用法。

    【讨论】:

    • 如果没有if constexpr,如何编译?我不明白为什么应该允许编译器丢弃 else 分支,除非 if (std::is_constant_evaluated()) 被特殊对待。
    • @HenriMenke memcpy存在 不是持续评估的问题,而是它的使用。持续评估的所有规则都是“你不能运行这个代码”,而不是“你不能在你的函数中拥有它”。例如在constexpr int f(bool b) { return b ? throw 0 : 0; }f(false) 中非常好。 throw 只有在我们到达它时才会中断。
    • 难道没有像样的编译器足够聪明,可以将第一个循环优化为与使用memcpy 相同吗?没有看过这类代码的编译输出,所以可能我对编译器的优化能力过于乐观。
    • @hyde 即使他们可以,仍然有人要求快速调试构建,这就是为什么我们仍然在库方面进行大量优化,而不是始终依赖优化器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 2020-01-20
    • 2020-06-25
    相关资源
    最近更新 更多