[英]std::remove_if GCC implementation isn't efficient?
从这里的另一个问题似乎有证据表明,与以下实现相比,GCC 对std::remove_if
实现没有提供同等的效率:
static char str1[100] = "str,, ing";
size_t size = sizeof(str1)/sizeof(str1[0]);
int bad = 0;
int cur = 0;
while (str1[cur] != '\0') {
if (bad < cur && !ispunct(str1[cur]) && !isspace(str1[cur])) {
str1[bad] = str1[cur];
}
if (ispunct(str1[cur]) || isspace(str1[cur])) {
cur++;
} else {
cur++;
bad++;
}
}
str1[bad] = '\0';
定时输出:
0.106860
用于解决同一问题的std::remove_if
示例基准代码:
bool is_char_category_in_question(const char& c) {
return std::ispunct(c) || std::isspace(c);
}
std::remove_if(&str1[0], &str1[size-1], is_char_category_in_question);
定时输出:
1.986838
请检查并获取运行上面 ideone 链接的代码的实际运行时结果(在此处提供完整代码会使问题变得模糊!)。
鉴于提供的执行时间结果(来自示例),这些似乎证实第一个实现具有更好的性能。
谁能说出原因,为什么std::remove_if()
算法没有(或不能)为给定的问题提供类似的有效解决方案?
在我看来,由于size
为 100,您似乎在 100 个字符的范围内运行remove_if
,但“自制程序”运行直到您找到 nul 终止符(其中只有 10 个字符)。
使用下面评论中的更改处理该问题,在使用 -O2 的 GCC 上,我仍然看到大约 2 倍的差异, remove_if
速度较慢。 更改为:
struct is_char_category_in_question {
bool operator()(const char& c) const {
return std::ispunct(c) || std::isspace(c);
}
};
消除了几乎所有这些差异,尽管可能仍然存在 <10% 的差异。 所以这在我看来像是一个实现质量问题,尽管我没有检查程序集以确认测试是否被内联。
由于您的测试工具意味着在第一次通过后实际上没有删除任何字符,因此我不会因 10% 的差异而感到困扰。 我有点惊讶,但还不足以真正进入它。 YMMV :-)
您可以尝试使用擦除-删除习语进行小幅改进。
std::string str{str1};
for(i=0;i<999999L;++i) {
str.erase( std::remove_if(std::begin(str), std::end(str), is_char_category_in_question), std::end(str) );
}
这与 Steve Jessop 提到的另一个问题结合在一起,所以我用10
替换了size - 1
但如果你愿意,你可以使用strlen
。 对于这个测试,我的 Makefile 看起来像:
compile:
g++ test.cpp -o test -std=c++11 -O3
g++ test2.cpp -o test2 -std=c++11 -O3
g++ test3.cpp -o test3 -std=c++11 -O3
run:
perf stat -r 10 ./test
perf stat -r 10 ./test2
perf stat -r 10 ./test3
test
是erase-remove 版本, test2
是remove_if
版本, test3
是另一个版本。 结果如下:
Performance counter stats for './test' (10 runs):
0.035699861 seconds time elapsed ( +- 2.30% )
perf stat -r 10 ./test2
Performance counter stats for './test2' (10 runs):
0.050991938 seconds time elapsed ( +- 2.96% )
perf stat -r 10 ./test3
Performance counter stats for './test3' (10 runs):
0.038070704 seconds time elapsed ( +- 2.34% )
我省略了冗长的信息,只运行了 10 次。 您可以自己尝试测试以更好地解释结果。
为什么不使用 lambda ?
要从向量 v 中删除偶数 int :
int main (int argc, char* argv []) {
int tmp [5] = {1, 2, 4, 5, 7};
int* p ((int*) tmp);
std::vector<int> v (p, p+5);
std::cout << "v init :";
for (auto i (v.begin ()); i != v.end (); ++i) std::cout << *i << " ";
std::cout << std::endl;
auto i (v.begin ());
std::for_each (v.begin (), v.end (), [&i] (const int s) {
if (s%2) *i++ = s;
});
if (i != v.end ()) v.erase (i, v.end ());
std::cout << "v odd :";
for (auto i (v.begin ()); i != v.end (); ++i) std::cout << *i << " ";
std::cout << std::endl;
}
正常输出:
v init :1 2 4 5 7
v odd :1 5 7
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.