c++中的循环融合(如何帮助编译器?)

Loop fusion in C++ (how to help the compiler?)

本文关键字:帮助 何帮助 编译器 循环 融合 c++      更新时间:2023-10-16

我试图理解在什么情况下c++编译器能够执行循环融合,什么时候不能。

下面的代码测量了计算向量中所有值的平方双精度数(f(x) = (2*x)^2)的两种不同方法的性能。

#include <chrono>
#include <iostream>
#include <numeric>
#include <vector>
constexpr int square( int x )
{
    return x * x;
}
constexpr int times_two( int x )
{
    return 2 * x;
}
// map ((^2) . (^2)) $ [1,2,3]
int manual_fusion( const std::vector<int>& xs )
{
    std::vector<int> zs;
    zs.reserve( xs.size() );
    for ( int x : xs )
    {
        zs.push_back( square( times_two( x ) ) );
    }
    return zs[0];
}
// map (^2) . map (^2) $ [1,2,3]
int two_loops( const std::vector<int>& xs )
{
    std::vector<int> ys;
    ys.reserve( xs.size() );
    for ( int x : xs )
    {
        ys.push_back( times_two( x ) );
    }
    std::vector<int> zs;
    zs.reserve( ys.size() );
    for ( int y : ys )
    {
        zs.push_back( square( y ) );
    }
    return zs[0];
}
template <typename F>
void test( F f )
{
    const std::vector<int> xs( 100000000, 42 );
    const auto start_time = std::chrono::high_resolution_clock::now();
    const auto result = f( xs );
    const auto end_time = std::chrono::high_resolution_clock::now();
    const auto elapsed = end_time - start_time;
    const auto elapsed_us = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
    std::cout << elapsed_us / 1000 << " ms - " << result << std::endl;
}
int main()
{
    test( manual_fusion );
    test( two_loops );
}

使用两个循环的版本花费的时间是使用一个循环的版本的两倍,即使GCC和Clang使用-O3也是如此。

是否有一种方法可以让编译器优化two_loops,使其与manual_fusion一样快,而无需在第二个循环中操作?我问的原因是我想让链接调用我的库FunctionalPlus像fplus::enumerate(fplus::transform(f, xs));更快。

你可以试着这样修改你的two_loops函数:

int two_loops( const std::vector<int>& xs )
{
    std::vector<int> zs;
    zs.reserve( xs.size() );
    for ( int x : xs )
    {
        zs.push_back( times_two( x ) );
    }
    for ( int i=0 : i<zs.size(); i++ )
    {
        zs[i] = ( square( zs[i] ) );
    }
    return zs[0];
}
关键是要避免两次分配内存和push_back到另一个vector