为什么C++中的sort比C中的qsort慢非常非常多啊?

chinesefox0426 2007-07-11 07:02:58
对比了std::sort和qsort,发现速度差异相当大,至少100倍,请大家帮我分析一下原因吧,非常感谢!!

char **text;

text = new char *[1000000];

/* text赋值部分省略 */

/* 用C中的qsort,大概10s左右就可以完成 */
int comp(char **p, char **q)
{ return strcmp(*p, *q); }
qsort(text, 1000000, sizeof(char *), comp);

/* 用C++中的std::sort,花了十分钟了还没有结果 */
bool cmp(const char *p, const char *q)
{ return strcmp(p, q) < 0 ? true : false; }
std::sort(text, text + 1000000, cmp);

...全文
2685 40 打赏 收藏 转发到动态 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
taodm 2007-07-12
  • 打赏
  • 举报
回复
那么建议你向gcc开发组提交bug报告。
还能怎么办呢。
chinesefox0426 2007-07-12
  • 打赏
  • 举报
回复
to iambic():
我今天也发现了这个问题,真是柳暗花明又一村啊,不过我的代码没你写得帅,我的代码如下:
bool comp(const char *p, const char *q)
{
if (p == q) return false;
return strcm(p, q) < 0;
}

我结贴早了点,没有给您加上分,抱歉啊。。。。

chinesefox0426 2007-07-12
  • 打赏
  • 举报
回复
to taodm:
用stable_sort就OK了,结果如下:
qsort 10.2s
stable_sort 9.2s
sort 10m+

这是为啥啊?
taodm 2007-07-12
  • 打赏
  • 举报
回复
你可以用stable_sort再试试。
taodm 2007-07-12
  • 打赏
  • 举报
回复
那么建议你向gcc开发组提交bug报告。
还能怎么办呢。
chinesefox0426 2007-07-12
  • 打赏
  • 举报
回复
taodm:
嗯,int型还是std::sort快,
很奇怪的是我以上的两段代码在VS2005中性能几乎相等,在GNU GCC(G++)中差异非常明显
iambic 2007-07-12
  • 打赏
  • 举报
回复
调试了差不多一个小时,我想我找到原因了。

你把C++版本的比较函数改下即可:

bool cmp(const char *p, const char *q)
{ return p==q ? false : strcmp(p, q) < 0 }

简单的说,因为GCC版本的std::sort会有机会使用strcmp比较自己,而这个strcmp的代价是和字符串长度成精确正比的——在你的算法里,恰好绝大多数字符串都长的变态(平均长度是1M)。就是这些超长字串不断将自身按内容比较导致了性能的急剧下降。按我的方法稍适修改后就正常了

出现自身比较这种情况很可能是GCC使用的某种细节优化技巧,而qsort和VC没有使用这样的技巧,所以没出现问题。

细节可以自己阅读《STL源码剖析》,或者直接看STL源码。估计是在partition或者unguarded linear insert附近。

今天就到这里,还有问题明天可以继续讨论。可惜你结贴太早了……
taodm 2007-07-12
  • 打赏
  • 举报
回复
算楼主狠!
quicksort是一种平均效率最高的算法,但是受所排序数据影响是比较重的。
sort比qsort快也是基于平均的。
你换5000000个随机int值再测试呢?
chinesefox0426 2007-07-12
  • 打赏
  • 举报
回复
to Vitin(卫亭):
我自己写了一个strcmm函数来替代strcmp,效果一样,QSORT 10+秒,std::sort 10+分钟
编译环境:GNU GCC(G++) Ver 3.3.5 -O2

QucikSort的代码

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
inline int strcmm(const char *src, const char *dst)
{
int ret = 0;
while (!(ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
++src, ++dst;

if (ret < 0)
return -1;
if (ret > 0)
return 1;
return ret;
}

int pstrcmp(char **p, char **q)
{ return strcmm(*p, *q); }

#define MAXN 5000000
char c[MAXN], *a[MAXN];

int main()
{ int ch, n = 0;
while ((ch = getchar()) != EOF) {
a[n] = &c[n];
c[n++] = ch;
}
c[n] = 0;
qsort(a, n, sizeof(char *), pstrcmp);
return 0;
}




std::sort的代码

#include <iostream>
#include <algorithm>
using namespace std;

inline int strcmm(const char *src, const char *dst)
{
int ret = 0;

while (!(ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
++src, ++dst;
if (ret < 0)
return -1;

if (ret > 0)
return 1;

return ret;

}


inline bool comp(const char *p, const char *q)
{
return strcmm(p, q) < 0;
}

#define MAXN 5000000
char c[MAXN], *a[MAXN];

int main()
{ int ch, n = 0;
while ((ch = getchar()) != EOF) {
a[n] = &c[n];
c[n++] = ch;
}
c[n] = '\0';

std::sort(a, a + n, comp);
return 0;
}



chinesefox0426 2007-07-12
  • 打赏
  • 举报
回复
to Vitin(卫亭):
引用
字符串没关系的.LZ的测试用例相当于1000000个字符串,它们的长度分别为1到1000000.两边使用的都是同样的字符串,排序的是每个字符串的头指针.

确实是这个意思

引用
也可能是和strcmp的实现有关系。

建议自己写一个strcmp,然后做测试,这样问题就局限在 qsort / std::sort 上了.


好主意,我去试一下
chinesefox0426 2007-07-12
  • 打赏
  • 举报
回复
to taodm:
确实是把整个a作为一个很大字符串来处理的
Vitin 2007-07-12
  • 打赏
  • 举报
回复
字符串没关系的.LZ的测试用例相当于1000000个字符串,它们的长度分别为1到1000000.两边使用的都是同样的字符串,排序的是每个字符串的头指针.

Vitin 2007-07-12
  • 打赏
  • 举报
回复
也可能是和strcmp的实现有关系。

建议自己写一个strcmp,然后做测试,这样问题就局限在 qsort / std::sort 上了.
taodm 2007-07-12
  • 打赏
  • 举报
回复
一共才一个\0,那么一共只能算一个字符串啊
chinesefox0426 2007-07-12
  • 打赏
  • 举报
回复
to taodm:

while ((ch = getchar()) != EOF) {
a[n] = &c[n];
c[n++] = ch;
}
c[n] = 0; //在这里加的,我把这个改成c[n] = '\0',结果还是一样。。。
hzhxxx 2007-07-12
  • 打赏
  • 举报
回复
gcc --version

gcc (GCC) 3.3.6
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

我用这个版本,大家用什么版本??
taodm 2007-07-12
  • 打赏
  • 举报
回复
你字符串的结束用的\0是在哪加的?
chinesefox0426 2007-07-12
  • 打赏
  • 举报
回复
to Chiyer(星羽)
我觉得std::sort慢跟我的数据集有点关系,我在13楼贴出了我的代码,能帮我分析一下吗?
更奇怪的事情是在VC2005环境下,两种方式速度差异不大,但在Linux GNU GCC编译下,速度差异相当明显啊
  • 打赏
  • 举报
回复
std::sort要比qsort要快的。
chinesefox0426 2007-07-12
  • 打赏
  • 举报
回复
to taodm:
我打印出来看过了,是正确的啊
加载更多回复(20)

64,701

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧