首页 > 解决方案 > std::transform 比 for 循环慢

问题描述

我考虑过实现一个std::transform从算法中用于计算的矩阵类,但我发现在某些情况下编写循环更快。

看看添加operator+=元素明智的添加。如果 rhs 矩阵有 1 col 而行数与 lhs 矩阵相同,我可以执行以下操作:

for (auto c = 0; c < cols(); ++c) {
    std::transform(std::execution::par, col_begin(c), col_end(c), rhs.begin(), col_begin(c), std::plus<>());
}

或使用简单的循环:

auto lhsval = begin();
auto rhsval= rhs.begin();

for (auto r = 0; r < rows(); ++r) {
   for (auto c = 0; c < cols(); ++c) {
       *lhsval += *rhsval;
       ++lhsval;
   }
   ++rhsval;
}

为了您的信息,我写了一个接受一个步骤的迭代器。所以col_begin()返回一个迭代器,它将跳过中的其他列operator++

我使用谷歌基准测试了两种实现之间的差异,并得出结论,循环比使用 std::transform 快大约 5 倍。好吧,也许应该有区别,但没有那么大的区别。

你可以在我的 github repo中查看完整的代码

矩阵类 矩阵迭代器

标签: c++matrixc++17

解决方案


传递std::execution::par是要求库并行化此操作。这会增加开销,即使只是为了确定“您的问题太小而无法并行化”。在并行化值得之前,被转换的元素数量必须非常大(有时数十万或数百万),并且需要您拥有适当的硬件(在两核机器上并行化比在64 核机器)。

for循环版本更类似于std::transform没有std::execution::par参数的普通版本。如果您删除该参数并且性能差异仍然很大,请使用该信息更新您的问题,以及您的编译器版本、平台、编译器开关和有关您的数据集的信息:行数/列数等。


推荐阅读