c++ - 嵌套的 std::transform 效率低吗?
问题描述
如果我有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); });
但是,如果我有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
版本生成了一半以上的程序集,并且相应地表现不佳,这让我感到惊讶。
在这种情况下不是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;
});
我在您的链接中添加了两个新的 quickbench 功能。一种将输入字符串作为引用传递。另一个也通过引用返回。那是:
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 测试实现。
推荐阅读
- apache-camel - 骆驼聚合策略
- imagemagick - 需要了解 ImageMagick 中的一段代码
- ios - 让精灵向各个方向移动
- c# - 从数组中删除一个元素?
- php - Ajax 和 htaccess - 仅重定向内容 div,复制整个模板
- assembly - 装配获取鼠标位置 (TASM)
- javascript - Javascript:如何从 JavaScript 对象中获取数字?
- reactjs - 使用 react-highcharts,尝试更新 xAxis 类别值,但它没有,它将值保留在我的配置变量中。
- html - 如何拆分每个幻灯片 CSS 的滑块设置
- amazon-web-services - AWS Cognito 使用与 SES 不同的电子邮件提供商