我一直试图通过char
减少std::stringstream
中的每个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 文本文件。
我没有使用优化版本。这是调试版本。目标是能够更快地运行代码以进行调试。此问题的发布结果是次要的。
有关如何提高效率的任何建议?
答案 0 :(得分:16)
如果您不将str
用于其他任何事情,我会考虑将其转换到位。这样,您可以回写到您读取的同一位置,并可能获得更好的缓存行为。只需更改
std::transform(str.begin(), str.end(), std::back_inserter(out), decrement);
到
std::transform(str.begin(), str.end(), str.begin(), decrement);
你可以完全摆脱你的out
字符串。允许第3个(目标)参数与第一个参数相同。
这不仅完全消除了额外的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);
答案 1 :(得分:5)
有两个明显的加速。
首先是就地改造。
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
,请使用&
代替#navlist:hover #left-arrow {
border-top: 10px solid white;
position: relative;
transform: translateX(120.2px) rotate(180deg);
}
。
在一个带有调试工具的迭代器的系统中,这可能会快得多。在优化的构建中,我希望它具有相同的速度。
答案 2 :(得分:4)
如果您需要额外的速度(比Raphael提供的解决方案快约5倍),我认为仍然可以接受(也取决于您的目标机器)稍微不那么优雅(ss intrinsics(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;