【问题标题】:Filling vector with emplace_back vs. std::transform用 emplace_back 与 std::transform 填充向量
【发布时间】:2021-09-22 18:39:30
【问题描述】:

这是一个简单的向量和类的过度简化的代码。

class OutputClass
{
public:
OutputClass(int x, int y);
};

std::vector<OutputClass> Convert(std::vector<int> const &input)
{
    std::vector<OutputClass> res;
    res.reserve(input.size());
    //either (1)
    for (auto const &in : input)
        res.emplace_back(in, in*in);
    return res;
    //or something like (2)
    std::transform(input.begin(), 
                   input.end(), 
                   std::back_inserter(res), 
                   [](InputClass const &in){return OutputClass(in, in*in);});
    return res;
}  

这两个选项的性能有区别吗?静态分析器通常具有用算法替换所有原始循环的规则,但在这种情况下,在我看来,使用 emplace_back 循环会更有效,因为我们不需要复制或移动。或者我错了,它们在性能方面是相同的,(2)在良好的风格和可读性方面更可取?

【问题讨论】:

  • Is there difference in performance in those two options?你可以通过测量找到。
  • 除非有back_emplacer,否则我会使用循环来放置和插入算法。它们表达的东西略有不同,即使经过优化后它们可能是相同的
  • 刮掉我的最后一条评论。我在C++ Quick Bench 上再次运行了替补席,emplace_back 版本稍微快了一点。当我最初运行测试时,我忘记了std::vector 中的reserve 空间用于std::transform bench
  • @WBuck 如果您声称有一些基准测试结果并链接quick-bench.com,为什么不包含指向您的结果的链接?我无法可靠地重现 emplace_backstd::transform 快:quick-bench.com/q/SoJQbRCSrkd5z2Kd04kh-S6jUkE
  • std::transform 允许您从 C++17 开始指定执行策略,允许您并行执行。可悲的是,它似乎不适用于 std::back_inserter。在对此进行试验时,我偶然发现了一个事实,对于您的简单示例,resize + 填充的速度是reserve + 插入的两倍。程序集显示 clang12 和 gcc10 无法矢量化插入循环——也许它们无法证明不需要调整大小? quick-bench.com/q/yKgW89g_4Q0GhYtTWIxPqs_Kzzc。 (注意:它运行的容器可能被限制为一个核心)

标签: c++ algorithm performance c++11 std


【解决方案1】:

要确定一个在特定用例中是否明显快于另一个,您可以进行测量。

我认为强制创建向量没有任何好处。在不需要时避免动态分配对性能非常有利。这是一个使用向量的示例,但这不是必需的:

OutputClass
convert(int in)
{
    return {in, in*in};
}

auto
convert_range(const auto& input)
{
    return std::ranges::transform_view(input, convert);
}

#include <vector>
int main()
{
    std::vector<int> input {1, 2, 3};
    auto r = convert_range(input);
    std::vector<OutputClass> output(r.begin(), r.end());
}

【讨论】:

    猜你喜欢
    • 2013-02-07
    • 2016-03-01
    • 2021-10-12
    • 2016-04-22
    • 2011-08-20
    • 2018-07-10
    • 1970-01-01
    • 2011-08-08
    • 2014-02-27
    相关资源
    最近更新 更多