You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用std::transform现代化改造并行C风格矩阵-向量乘法实现

矩阵-向量乘法的STL并行实现方案

问题背景

现有基于OpenMP并行的C风格矩阵-向量乘法实现(C[N] = A[N,M] * B[M]),需要改用STL的std::transform结合并行执行策略(如std::execution::par)实现现代化版本,核心问题是如何在std::transform的函数体内获取计算每个C元素所需的行索引,同时寻求其他STL替代方案。

基于std::transform的实现方案

std::transform默认迭代容器元素,但我们需要的是每个C元素的行索引来定位矩阵A中对应的行与向量B做点积。因此可以构造一个索引序列,通过迭代索引完成计算:

C++17兼容版本

由于C++17无范围库,先创建存储索引的临时向量,再执行std::transform:

template<typename T>
bool run_transform_based_solution(std::vector<T> &A, std::vector<T> &B, std::vector<T> &C, size_t N, size_t M)
{
    if (A.size() != N*M || B.size() != M || C.size() != N) return 1;

    // 构造索引序列:0,1,...,N-1
    std::vector<size_t> indices(N);
    std::iota(indices.begin(), indices.end(), 0);

    // 并行transform:每个索引i对应计算C[i] = A[i*M ... i*M+M-1] · B
    std::transform(std::execution::par,
                   indices.begin(), indices.end(),
                   C.begin(),
                   [&](size_t i) {
                       T sum = 0.0;
                       for (size_t j = 0; j < M; ++j) {
                           sum += A[i*M + j] * B[j];
                       }
                       return sum;
                   });

    return 0;
}

C++20优化版本(可选)

若升级到C++20,利用范围库std::views::iota可省去临时索引向量的开销:

#include <ranges>

template<typename T>
bool run_transform_based_solution(std::vector<T> &A, std::vector<T> &B, std::vector<T> &C, size_t N, size_t M)
{
    if (A.size() != N*M || B.size() != M || C.size() != N) return 1;

    std::transform(std::execution::par,
                   std::views::iota(0u, N).begin(), std::views::iota(0u, N).end(),
                   C.begin(),
                   [&](size_t i) {
                       T sum = 0.0;
                       for (size_t j = 0; j < M; ++j) {
                           sum += A[i*M + j] * B[j];
                       }
                       return sum;
                   });

    return 0;
}

其他STL替代方案

方案1:std::for_each并行版本

std::for_each同样支持并行执行策略,逻辑更贴近原OpenMP版本:

template<typename T>
bool run_for_each_based_solution(std::vector<T> &A, std::vector<T> &B, std::vector<T> &C, size_t N, size_t M)
{
    if (A.size() != N*M || B.size() != M || C.size() != N) return 1;

    std::vector<size_t> indices(N);
    std::iota(indices.begin(), indices.end(), 0);

    std::for_each(std::execution::par,
                  indices.begin(), indices.end(),
                  [&](size_t i) {
                      T sum = 0.0;
                      for (size_t j = 0; j < M; ++j) {
                          sum += A[i*M + j] * B[j];
                      }
                      C[i] = sum;
                  });

    return 0;
}

方案2:std::generate并行版本

若无需保留C初始值(已提前fill为0),可直接用std::generate生成每个C元素:

template<typename T>
bool run_generate_based_solution(std::vector<T> &A, std::vector<T> &B, std::vector<T> &C, size_t N, size_t M)
{
    if (A.size() != N*M || B.size() != M || C.size() != N) return 1;

    size_t i = 0;
    std::generate(std::execution::par,
                  C.begin(), C.end(),
                  [&]() mutable {
                      T sum = 0.0;
                      for (size_t j = 0; j < M; ++j) {
                          sum += A[i*M + j] * B[j];
                      }
                      i++;
                      return sum;
                  });

    return 0;
}

编译说明

所有代码需以-std=c++17(或-std=c++20)编译,部分编译器需额外添加-ltbb或-fopenmp以启用并行执行策略。

内容的提问来源于stack exchange,提问作者Andreas Hadjigeorgiou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 13:00:57