[C ++算法循环融合优化

问题描述 投票:2回答:1

我偶尔发现在我的代码中,我会有一个数据结构,我想从中获取两个或多个值,每个值都可以使用标准算法提取。问题是,使用标准算法意味着对数据进行多次循环。以下面的示例为例,其中我有一个vector<int>,并且想要获取总和,第一个元素的值超过某个阈值以及该阈值之上的元素总数:

constexpr auto GetValuesSTL(const std::vector<int>& testdata)
{
    constexpr auto value_above_threshold = [](const auto value) constexpr { return value > THRESHOLD; };
    constexpr auto optional_from_iterator = [](const auto it, const auto end) constexpr { return it != end ? std::make_optional(*it) : std::nullopt; };

    return std::make_tuple(
        std::accumulate(testdata.begin(), testdata.end(), 0L),
        optional_from_iterator(std::find_if(testdata.begin(), testdata.end(), value_above_threshold), testdata.end()),
        std::count_if(testdata.begin(), testdata.end(), value_above_threshold) );
}

但是我可以更有效地将其编写为原始循环:

constexpr auto GetValuesRawLoop(const std::vector<int>& testdata)
{
    auto sum = 0L;
    std::optional<int> first_above_threshold = std::nullopt;
    auto num_above_threshold = 0;

    auto it = testdata.begin();
    for (; it != testdata.end(); ++it)
    {
        const auto value = *it;

        if (value > THRESHOLD)
        {
            first_above_threshold = value;
            break;
        }

        sum += value;
    }
    for (; it != testdata.end(); ++it)
    {
        const auto value = *it;

        sum += value;

        if (value > THRESHOLD)
        {
            ++num_above_threshold;
        }
    }

    return std::make_tuple( sum, first_above_threshold, num_above_threshold );
}

我希望编译器能够将算法调用融合到一个循环中,因为它具有足够的信息来知道向量没有被修改,而是在随机生成的整数的各种长度向量上对这两个函数进行了分析(与g++-9 -O3编译)显示,该函数的STL版本持续花费原始循环的时间大约是2-2.5倍,这与不使用循环融合所期望的完全相同。]

是否有充分的理由编译器不能/不应用这种优化?是否需要某种假设才能融合不允许编译器进行的循环?还是检测和应用根本上困难的事情?有没有其他替代方法可以像原始循环一样有效,并且可以像算法版本一样表现力?

我偶尔发现在我的代码中,我会有一个数据结构,我想从中获取两个或多个值,每个值都可以使用标准算法提取。问题是,要使用...

c++ compiler-optimization
1个回答
0
投票

我将回答您问题的最后一部分:

© www.soinside.com 2019 - 2024. All rights reserved.