- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我目前正在尝试学习 C++11 及其花哨的功能。具体来说,我正在寻找高效的通用性。所以我很高兴地用 C++11 编写了一个程序来对输入文件的行进行排序,以测试我的新技能。由于 C++ 编译器的内联和很好的特性,我期望这个小例子有高性能。为了提示我的程序有多快,我使用 qsort
函数在 C 中破解了完全相同的程序,因为它是原始 C 没有对此函数执行内联,并且我的比较函数被调用间接访问,需要做两次间接访问 char *
表示字符串的指针。
然而,我对结果感到非常惊讶,C 似乎比 C++ 快 4 倍。在 8Mb 文件上,我得到以下结果:
$ g++ -O3 -std=c++11 -o sort sort.C
$ time ./sort < huge > /dev/null
real 0m0.415s
user 0m0.397s
sys 0m0.013s
$ cc -O3 -Wall -o sortc sort.c
$ time ./sortc < huge > /dev/null
real 0m0.104s
user 0m0.097s
sys 0m0.010s
$ wc -l huge
140190 huge
请注意,我尽量做到公平,编译选项是相同的,我的 C 程序(稍后转储)的行为方式与 C++ 程序相同:输入行的大小没有限制,也没有限制输入行数。
我还注意到,虽然我的 C 程序几乎为每个输入行调用一次 malloc
,但 C++ 程序每个输入行的分配比例为 10!
这是我用来比较的两个程序。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <memory>
int main () {
typedef std::vector<std::string> svec;
svec a;
std::string s;
for (;;) {
getline(std::cin, s);
if (std::cin.eof()) {
if (s != "")
a.push_back(std::move(s));
break;
}
a.push_back(std::move(s));
}
std::sort(a.begin(), a.end());
for (std::string &s : a) {
std::cout << s << "\n";
}
}
还有我更详细的 C 版本。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUFSZ 100
size_t getl(char **line, size_t len) {
char buf[BUFSZ];
size_t i, n;
for (i=0; i<BUFSZ; i++) {
int c = getchar();
if (c == EOF || c == '\n') {
*line = malloc(len+i+1);
memcpy(&(*line)[len], buf, i);
(*line)[len+i] = 0;
return i;
}
buf[i] = c;
}
n = getl(line, len+i);
memcpy(&(*line)[len], buf, i);
return i+n;
}
#define ARRAYSZ 30
struct Array {
char **lv;
size_t li, lc;
};
void addline(struct Array *a, char *line) {
if (a->li == a->lc) {
a->lc *= 2;
a->lv = realloc(a->lv, a->lc * sizeof *a->lv);
}
a->lv[a->li++] = line;
}
int cmp(const void *a, const void *b) {
return strcmp(*(const char **)a, *(const char **)b);
}
int main(void) {
char *line;
struct Array a;
size_t i;
a.li = 0;
a.lc = ARRAYSZ;
a.lv = malloc(a.lc * sizeof *a.lv);
for (;;) {
getl(&line, 0);
if (feof(stdin)) {
if (line[0] != 0)
addline(&a, line);
else
free(line);
break;
}
addline(&a, line);
}
qsort(a.lv, a.li, sizeof *a.lv, cmp);
for (i=0; i<a.li; i++) {
printf("%s\n", a.lv[i]);
free(a.lv[i]);
}
free(a.lv);
return 0;
}
有人能告诉我我的 C++ 程序必须在哪里更改(而不是变成纯 C)才能更快吗?我试图保持非常地道,这是破解 C++ 的好方法,还是当我想要高性能时应该倾向于编写类似 C 的代码?为什么 C++ 程序在堆上分配这么多,我该如何减少呢?
根据大众的需求,我展示了我的 C++ 程序的分析结果。这是我的 C++ 程序的分析器的有趣输出(前两行):
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ms/call ms/call name
40.03 0.02 0.02 1198484 0.00 0.00 __gnu_cxx::__normal_iterator<std::string*, std::vector<std::string, std::allocator<std::string> > >::operator--()
30.02 0.04 0.02 2206802 0.00 0.00 bool std::operator< <char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
当我读到它时,似乎分配不是唯一的原因。
最佳答案
原因在于 c++ std io 同步。以下代码:
int main () {
typedef std::vector<std::string> svec;
svec a;
std::string s;
// note
std::ios_base::sync_with_stdio(false);
for (;;) {
getline(std::cin, s);
if (std::cin.eof()) {
if (s != "")
a.push_back(std::move(s));
break;
}
a.push_back(std::move(s));
}
std::sort(a.begin(), a.end());
for (std::string &s : a) {
std::cout << s << "\n";
}
}
给予
real 0m0.106s
user 0m0.104s
sys 0m0.004s
C 版本给出了这个:
real 0m0.167s
user 0m0.164s
sys 0m0.000s
编辑:正如 RiaD 正确提到的,sync_with_stdio
当然是静态函数,因此对所有 std io 流调用一次函数就足够了。
关于c++ - 排序字符串 vector : plain C vs idiomatic C++11,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11985859/
我是 Mercurial 的新手,并且不知何故仍处于评估过程中,所以这四个概念对我来说有点困惑。有些被提到等同于 Git 的 Staging/Index 概念,有些甚至比 Git 的 Staging
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 6 个月前关闭。 Improve this ques
任何人都可以给我详细信息吗? 例如? #ID 是属性、特性、选择器还是 anchor ? 默认属性和默认属性是不同的东西吗? 这些都是标签还是元素? 我们将对此说些什么 这个 ..... 还有这些
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 8 年前。 Improve this qu
我有一个由 Javascript 填充的下拉列表。 在决定加载时显示的默认值时,我意识到以下属性显示的值完全相同: innerText innerHTML label text textContent
我可以知道每个 Exec 之间有什么区别吗? , ExecWait , ExecShell , nsExec::Exec , nsExec::ExecToLog, nsExec::ExecToStac
当您处于版本 1 和版本 2 之间时,您会如何维护您的软件? 从我的角度来看,“补丁”、“修补程序”、“维护版本”、“服务包”等术语都很模糊,根据与您交谈的对象不同,定义也不同。 您如何称呼版本之间的
我刚刚发现在 ES6 中有一个新的数学方法:Math.trunc . 我在 MDN article 中阅读了它的描述。 , 听起来像使用 |0 . 此外,>0 , &-1 , ^0也做类似的事情(感谢
我想知道我的 StackPanel 所有项目的高度。 有什么区别: Height - 获取或设置元素的建议高度。 ActualHeight - 获取该元素的渲染高度。 (只读) ExtentHeigh
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 9 年前。 Improve this
我对所有声称以某种方式阻止计算的内置 Mathematica 函数感到困惑:Unevaluated、Defer、Hold ,以及超过 6 个 Hold* 形式。 Mathematica 文档只是单独解
我什至不确定正确的术语,所以让我从我的目标开始:拥有一个简单的应用程序(“Data Doler”),它只会将大量数据从文件读取到内存中,然后提供服务将该数据切片到名为“Data Lapper”的单个多
我刚刚开始在我的项目中使用 Elasticsearch,我想像 sql 关键字一样搜索 '喜欢%' 做。 谁能解释一下 之间的区别通配符 , 前缀 , 查询字符串和 正则表达式 ? 哪个可以搜索最好性
由于我对任何主流浏览器(Firefox、Chrome、Opera)都不太满意,而且我尝试过的不太受欢迎的浏览器(近十几种)都没有,所以我决定 DIY 并制作一个网页我想要最好的浏览器。 主要目标是让它
我知道如何使用 Python 解析页面。我的问题是哪种方法是所有解析技术中最快的,其他方法的速度有多快? 我知道的解析技术有Xpath、DOM、BeautifulSoup,还有使用Python的fin
我试图从正在解析的命令行中找出哪个函数最适合将十进制、十六进制或八进制数转换为 int 最好——在不知道输入的情况下事先。 目标是使用一个函数来识别不同类型的输入并将其分配给它的整数 (int) 值,
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我们需要在我们的网站上显示酒吧、餐馆和剧院等各种场所的元信息(例如,地址、姓名)。 理想情况下,用户会输入地点名称以及邮政编码,我们会提供最接近的匹配项。 人们将哪些 API 用于类似的地理定位目的?
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我正在创建我的第一个 Web 应用程序,我真的很困惑应该使用什么技术。 我的应用程序需要看起来很严肃(像一个应用程序),它不需要很多色彩缤纷的图形界面。它只需要一个工具栏、一个标签栏、一个拆分面板(最
我是一名优秀的程序员,十分优秀!