c++ - 嵌套的 std::transform 效率低吗?

标签 c++ performance stl-algorithm

如果我有一个 std::string :

std::string s{"hello"};

以及一个就地修改它的循环,如下所示:

for (auto &c: s)
  c = std::toupper(c);

我可以将其替换为等效的 transform :

std::transform(s.begin(), s.end(), s.begin(),
               [](unsigned char c) -> unsigned char 
               { return std::toupper(c); });

这些片段生成相同的 assembly 。他们也有类似的performance .

但是,如果我有 std::vector<std::string> :

std::vector<std::string> v {"hello", "how", "are", "you"};

并就地修改它,如下所示:

for (auto & s : v)
  for (auto &c: s)
    c = std::toupper(c);

等效的变换应该是:

std::transform(std::begin(v), std::end(v), std::begin(v),
  [](auto s) {
    std::transform(std::begin(s), std::end(s), std::begin(s), 
      [](unsigned char c) -> unsigned char { return std::toupper(c); });
    return s;
});

但是,transform版本生成的数量超过一半 assembly ,和performs相应地很差,这让我感到惊讶。

std::transform在这种情况下不是零成本抽象,或者我只是错误地使用它?

最佳答案

通过引用传递和返回所有内容。否则,您将复制该字符串的多个拷贝。请注意更改:[](auto& s) -> std::string& {

std::transform(std::begin(v), std::end(v), std::begin(v),
  [](auto& s) -> std::string& {
    std::transform(std::begin(s), std::end(s), std::begin(s), 
      [](unsigned char c) -> unsigned char { return std::toupper(c); });
    return s;
});

我在您的链接中添加了两个新的快速工作台函数。一种将输入字符串作为引用传递的字符串。另一个也通过引用返回。即:

static void Transform2(benchmark::State& state) {
  // Code before the loop is not measured

  std::vector<std::string> v {"hello", "how", "are", "you"};
  for (auto _ : state) {
    std::transform(std::begin(v), std::end(v), std::begin(v),
    [](auto& s) {
      std::transform(std::begin(s), std::end(s), std::begin(s), 
        [](unsigned char c) -> unsigned char { return std::toupper(c); });
      return s;
    });

  }
}
BENCHMARK(Transform2);


static void Transform3(benchmark::State& state) {
  // Code before the loop is not measured

  std::vector<std::string> v {"hello", "how", "are", "you"};
  for (auto _ : state) {
    std::transform(std::begin(v), std::end(v), std::begin(v),
    [](auto& s) -> std::string& {
      std::transform(std::begin(s), std::end(s), std::begin(s), 
        [](unsigned char c) -> unsigned char { return std::toupper(c); });
      return s;
    });

  }
}
BENCHMARK(Transform3);

根据我运行基准测试时的幸运程度,Transform3 的性能几乎(有时等于)InPlace 测试实现。

enter image description here

关于c++ - 嵌套的 std::transform 效率低吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61263702/

相关文章:

c++ - 我应该只为一个电话在免费商店上创建对象吗?

c++ - 如何使用偏航、俯仰和滚动来旋转 3D vector ?

c++ - 这两个条件句等价吗?

java - "Runtime.getRuntime().exec()"性能不好吗?

c++ - 在二维 std::array 上使用 std::accumulate

c++ - 在函数模板中,如何根据另一个参数确定一个参数的类型

javascript - 创建 BitmapData 并从中创建 Sprite 以及可能的性能差异

c# - 创建大量小文件的最佳方法?

c++ - 将 vector 的元素求和分配给另一个 vector 的元素的并行算法

c++ - 如何在 C++ 中实现类似 for_each 的函数?