转换大约 150mb 的字符串的快速方法
Fast method to transform a string with about 150mb
我一直在尝试将std::stringstream
中的每个char
值减少100
:
std::string str = stream.str();
auto decrement = [](char c) { return c - 100; };
std::string out;
out.reserve(str.size());
std::transform(str.begin(), str.end(), std::back_inserter(out), decrement);
stream = std::stringstream(out);
但是花了7分钟的时间坚持std::transform
指令。对于 150mb 的文本文件。
我没有使用优化的版本。这是调试版本。目标是能够使代码更快地运行以进行调试。对于此问题,发布结果是次要的。
关于如何提高效率的任何建议?
如果您不使用str
进行其他任何操作,我会考虑的一件事是将其转换为原地。这样,您就可以写回从中读取的同一位置,并且可能会获得更好的缓存行为。只需更改
std::transform(str.begin(), str.end(), std::back_inserter(out), decrement);
自
std::transform(str.begin(), str.end(), str.begin(), decrement);
你可以完全摆脱你的out
字符串。第三个(目标)参数允许与第一个参数相同。
这不仅完全摆脱了额外的 150MB 字符串变量,而且您以前必须访问内存中应该相距甚远的两个不同位置。通过读取和写回同一位置,您可以确保确实最大限度地利用了缓存。
当然,这会str
变异,所以只有当你不需要原始的str
变量做其他事情时,它才真正有用。
最终结果:
std::string str = stream.str();
auto decrement = [](char c) { return c - 100; };
std::transform(str.begin(), str.end(), str.begin(), decrement);
stream = std::stringstream(str);
有两个明显的加速。
首先是就地转换。
std::string str = stream.str();
auto decrement = [=](char c) { return c -= 100; };
std::transform(str.begin(), str.end(), str.begin(), decrement);
stream = std::stringstream(str);
被拉斐尔覆盖。
第二个,只是因为你想要 DEBUG 优化的速度,是绕过可能的调试迭代器检查。
std::string str = stream.str();
auto decrement = [=](char c) { return c -= 100; };
std::transform(&str[0], (&str[0])+str.size(), (&str[0]), decrement);
stream = std::stringstream(str);
在这里,我们将begin()
替换为 &str[0]
,一个指向字符缓冲区内容的原始指针。 如果您正在使用非常奇怪的basic_string
,请使用 std::addressof
而不是 &
。
在具有调试检测的迭代器的系统中,这可能会快得多。 在优化的版本中,我希望它的速度相同。
稍微
不那么优雅,但我认为仍然可以接受(也取决于您的目标机器)如果您需要额外的速度(比 Raphael 提供的解决方案快约 5 倍),请使用 sse 内联函数 (SSE2)。
#include <emmintrin.h>
__m128i dec = _mm_set1_epi8(100);
size_t x = 0;
for (; x < str.size()-15; x+=16)
{
__m128i sse = _mm_loadu_si128((__m128i*)&str[x]);
_mm_storeu_si128((__m128i*)&str[x], _mm_sub_epi8(sse, dec));
}
for (; x < str.size(); ++x)
str[x] -= 100;
相关文章:
- 有哪些有效的方法可以消除一组 100 万个字符串>重复数据?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 具有字符串化的可变参数宏的现代/通用方法
- 接收字符串并使用它来调用方法C++
- 如何分隔字符串并将标记传递给方法
- 是否有通用方法可以找到任何以 null 结尾的字符串的长度?
- 当映射包含字符串向量作为值时,从值中获取键的有效方法
- 在 C++11 中字符串化变量名称的替代方法
- 连接和压缩标准::vector<std::字符串的最佳方法>
- Esp8266 & Nodemcu:返回请求字符串的方法
- 将位字符串转储到二进制文件的最佳方法是什么
- 有没有一种 STL 方法可以找到字符串的所有排列,给出一个以 C++ 为单位的大小?
- 如何将字符串从 C++/CLI 方法返回到调用它的非托管C++
- 创建字符串数组的有效方法
- 如何使用字符串::replace方法写入文件
- 是否有更有效的方法来生成日期的REGEX字符串
- C++-将对象(如字符串)映射到表中成员函数的正确方法
- 有没有更快的方法从成员函数返回格式化字符串
- 有没有一种方法可以在不复制数据的情况下从string_view创建字符串流
- 从c++中的类指针对象调用方法(字符串)