【问题标题】:How to rewrite a nested loop using the C++ STL algorithms?如何使用 C++ STL 算法重写嵌套循环?
【发布时间】:2013-11-09 18:49:02
【问题描述】:

循环很简单,但我似乎无法使用 STL 算法来给出下面相同的嵌套循环。

const int a_size = 5; // input
const int c_size = 2; // output
const int b_size = a_size * c_size; // multipliers

std::vector<float> a(a_size);
std::vector<float> b(b_size);
std::vector<float> c(c_size);

// fill a and b with data

// this nested loop
for(int i = 0; i<c_size; i++) {
    c[i] = 0.0;
    for(int k = 0; k<a_size; k++) {
        c[i] += (a[k] * b[i*a_size+k]);
    }
    c[i] = sigmoid(c[i]);
}

我想这样做的原因是为了 Boost.Compute 库,它会使用类似 STL 的算法(std::transform、std::for_each 等)在 GPU 上进行计算。

【问题讨论】:

  • 似乎可以使用矩阵运算重写您的算法。
  • 我认为允许用户在Boost.Compute 中编写任意内核会更好——它会更有用。例如通过我描述的TaskGraph 方法here

标签: c++ algorithm for-loop vector stl


【解决方案1】:

其实嵌套循环就是算法std::inner_product。

auto first = std::begin( b );
auto increment = std::distance( std::begin( a ), std::end( a ) );
//,,

c[i] = std::inner_product( std::begin( a ), std::end( a ), first, 0 );
std::advance( first, increment );

您可以使用算法 std::generate 代替外部循环。

【讨论】:

    【解决方案2】:

    我来了with

    auto i = 0;
    generate(begin(c), end(c), [&i, &a, &b]
    {
        return sigmoid(inner_product
        (
            begin(a), end(a),
            begin(b) + distance(begin(a), end(a)) * i++, 0.f
        ));
    });
    

    但它看起来不太好 - 可能在这种情况下我更愿意编写自己的算法。

    或者使用矩阵形式。使用Eigen 库,它将变成:

    MatrixXd b;
    VectorXd a, c;
    // ...
    c = (b*a).unaryExpr(sigmoid);
    

    【讨论】:

    • 这需要我一段时间来消化。没听说过 Eigen,它支持 GPU 上的计算吗?
    • @user1973386 AFAIK - 目前它不支持 GPU。虽然它通过内在函数(SSE2 等)进行矢量化。我刚刚发现以下内容:gpumatrix - “GPU 上的矩阵和数组库,其接口与 Eigen 兼容” - 我认为也值得一看。
    • 太糟糕了,它还不支持 OpenCL,但是已经计划好了。我会跟踪那个库:)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多