首页 > 解决方案 > emplace_back 比在 c++11 中分配一次 + 移动更快?

问题描述

我有两个功能:

f2 - 首先分配内存,然后移动数据。

f - 释放 + 移动 = emplace_back。

我试图了解在性能和代码质量方面使用什么更快更好?

void f2(const std::vector<std::string>& users) {
    std::vector<std::pair<std::string, int>> userOccurancies(users.size());

    auto userOcIt = userOccurancies.begin();
    for (const auto & user : users) {
        userOcIt->first = std::move(user);
        userOcIt->second = 0;
        userOcIt++;
    }
}

void f(const std::vector<std::string>& users) {
    std::vector < std::pair<std::string, std::size_t>> userCount;
    userCount.reserve(users.size());

    for (auto& user : users) {
        userCount.emplace_back(user, 0);
    }
}

至于性能,我尝试使用 MS VS2019 分析器对其进行检查,但如果这些函数相互交换调用,它总是会给我不同的结果:f2(users);f(users);f(users);f2(users);给出不同的调用树。

你能帮助我吗?

就性能和代码质量而言,使用什么更快更好?

我只使用 c++11。

标签: c++performancec++11

解决方案


我在 quick-bench 网站上对其进行了测试,帖子中的代码结果表明 f2()(分配 + 复制)在 gcc 和 clang c++11 -O3 上都比 f() (emplace_back) 慢。

但在那之后我稍微改变了代码:

void f2(benchmark::State& state) {
    std::vector<std::string> users = { "john", "atest", "qwe" };
  for (auto _ : state) {
    std::vector<std::pair<std::string, int>> userOccurancies(users.size());

    auto userOcIt = userOccurancies.begin();
    for (auto && user : users) {
        userOcIt->first = std::move(user);
        userOcIt->second = 0;
        userOcIt++;
    }
  }
}
// Register the function as a benchmark
BENCHMARK(f2);

void f(benchmark::State& state) {
      std::vector<std::string> users = { "john", "atest", "qwe" };
  for (auto _ : state) {
    std::vector < std::pair<std::string, std::size_t>> userCount;
    userCount.reserve(users.size());

    for (auto&& user : users) {
        userCount.emplace_back(user, 0);
    }
  }
}
BENCHMARK(f);

不知道这个链接能工作多久http://quick-bench.com/CZIVnB4xVRBPpvw06GQ38FNkwws

主要变化 -for这次我在循环中删除const并将右值设为值。

现在f2(user);在 c++11 -O3 gcc 和 clang 下工作得更快,所以emplace_back这次输了。

f2() 比 f()快1.5 倍。

但如果users输入参数将包含大数据(8k 元素),则 f2()比 f()1.2 倍。

由于@JérômeRichard 评论而更新


推荐阅读