C++ iostream与C标准stdio的性能/开销比较

C++ iostream与C标准stdio的性能/开销比较

我正在努力理解如何改善这个基于C++的代码的性能,使其与基于C的代码保持一致。C代码如下:

#include

#include

#include

typedef struct point {

double x, y;

} point_t;

int read_point(FILE *fp, point_t *p) {

char buf[1024];

if (fgets(buf, 1024, fp)) {

char *s = strtok(buf, " ");

if (s) p->x = atof(s); else return 0;

s = strtok(buf, " ");

if (s) p->y = atof(s); else return 0;

}

else

return 0;

return 1;

}

int main() {

point_t p;

FILE *fp = fopen("biginput.txt", "r");

int i = 0;

while (read_point(fp, &p))

i++;

printf("read %d points\n", i);

return 0;

}

C++代码如下:

#include

#include

using namespace std;

struct point {

double x, y;

};

istream &operator>>(istream &in, point &p) {

return in >> p.x >> p.y;

}

int main() {

point p;

ifstream input("biginput.txt");

int i = 0;

while (input >> p)

i++;

cout << "read " << i << " points" << endl;

return 0;

}

我喜欢C++代码更短、更直接的特点,但是当我在同一台机器上运行它们(对138 MB的测试文件进行测试)时,它们的性能非常不同:

$ time ./test-c

read 10523988 points

1.73 real 1.68 user 0.04 sys

# subsequent runs:

1.69 real 1.64 user 0.04 sys

1.72 real 1.67 user 0.04 sys

1.69 real 1.65 user 0.04 sys

$ time ./test-cpp

read 10523988 points

14.50 real 14.36 user 0.07 sys

# subsequent runs

14.79 real 14.43 user 0.12 sys

14.76 real 14.40 user 0.11 sys

14.58 real 14.36 user 0.09 sys

14.67 real 14.40 user 0.10 sys

连续运行这两个程序多次并不会改变结果,即C++版本大约比Python版本慢10倍。

文件格式只是空格分隔的双精度数值行,例如:

587.96 600.12

430.44 628.09

848.77 468.48

854.61 76.18

240.64 409.32

428.23 643.30

839.62 568.58

有没有什么技巧可以减少我所忽略的开销?

编辑1:将运算符设置为内联似乎有一个非常小但可能可探测的影响:

14.62 real 14.47 user 0.07 sys

14.54 real 14.39 user 0.07 sys

14.58 real 14.43 user 0.07 sys

14.63 real 14.45 user 0.08 sys

14.54 real 14.32 user 0.09 sys

这并没有真正解决问题。

编辑2: 我正在使用clang:

$ clang --version

Apple LLVM version 7.0.0 (clang-700.0.72)

Target: x86_64-apple-darwin15.5.0

Thread model: posix

我在我的Mac上使用相同版本的Clang编译C和C++,没有使用任何优化级别。很可能使用的是OS X 10.11上Xcode (/usr/bin/clang)提供的版本。如果我只在其中一个启用优化或使用不同的编译器,可能会让问题变得复杂。

编辑3:用其他内容替换istream &operator>>

我重新编写了istream运算符,更接近于C版本,并且有所改进,但我仍然看到约5倍的性能差距。

inline istream &operator>>(istream &in, point &p) {

string line;

getline(in, line);

if (line.empty())

return in;

size_t next = 0;

p.x = stod(line, &next);

p.y = stod(line.substr(next));

return in;

}

运行:

$ time ./test-cpp

read 10523988 points

6.85 real 6.74 user 0.05 sys

# subsequently

6.70 real 6.62 user 0.05 sys

7.16 real 6.86 user 0.12 sys

6.80 real 6.59 user 0.09 sys

6.79 real 6.59 user 0.08 sys

有趣的是,使用 -O3 进行编译可以显著提高性能:

$ time ./test-cpp

read 10523988 points

2.44 real 2.38 user 0.04 sys

2.43 real 2.38 user 0.04 sys

2.49 real 2.41 user 0.04 sys

2.51 real 2.42 user 0.05 sys

2.47 real 2.40 user 0.05 sys

编辑4:将istream运算符>>的主体替换为C语言代码

这个版本已经接近C语言的性能:

inline istream &operator>>(istream &in, point &p) {

char buf[1024];

in.getline(buf, 1024);

char *s = strtok(buf, " ");

if (s)

p.x = atof(s);

else

return in;

s = strtok(NULL, " ");

if (s)

p.y = atof(s);

return in;

}

不经过优化的测量结果为2秒左右,经过优化后的时间超过了未经优化的C语言(尽管经过优化的C语言仍然胜出)。准确地说,没有进行优化:

2.13 real 2.08 user 0.04 sys

2.14 real 2.07 user 0.04 sys

2.33 real 2.15 user 0.05 sys

2.16 real 2.10 user 0.04 sys

2.18 real 2.12 user 0.04 sys

2.33 real 2.17 user 0.06 sys

使用:

1.16 real 1.10 user 0.04 sys

1.19 real 1.13 user 0.04 sys

1.11 real 1.06 user 0.03 sys

1.15 real 1.09 user 0.04 sys

1.14 real 1.09 user 0.04 sys

仅使用优化后的C语言,以实现同类比较:

0.81 real 0.77 user 0.03 sys

0.82 real 0.78 user 0.04 sys

0.87 real 0.80 user 0.04 sys

0.84 real 0.77 user 0.04 sys

0.83 real 0.78 user 0.04 sys

0.83 real 0.77 user 0.04 sys

我认为我可以接受这种情况,但作为一个初学者的C++用户,现在我想知道:

是否值得尝试其他方法?我不确定在istream operator>>内部发生什么事情是否重要。

除了以下三种方式外,是否有另一种构建C++代码的更好方法?

这种用法是否符合惯用法?如果不是,大多数人是否只接受其性能?

编辑5:这个问题与printf回答完全不同,我不明白所谓的重复链接如何直接解决上面提到的三个问题。

相关推荐

怎么查自己宽带是否欠费
365取消提款

怎么查自己宽带是否欠费

📅 07-29 👁️ 7321
摩拜单车怎么办年卡 月卡办理方法
约彩365手机下载安装

摩拜单车怎么办年卡 月卡办理方法

📅 08-15 👁️ 3846
【重装系统】Win10最新安装教程【保姆级】
365bet备用在线

【重装系统】Win10最新安装教程【保姆级】

📅 08-08 👁️ 1363
5分钟学会掼蛋
约彩365手机下载安装

5分钟学会掼蛋

📅 08-14 👁️ 698
《李凭箜篌引》
365bet备用在线

《李凭箜篌引》

📅 08-15 👁️ 1901
李太白集作者:李白
约彩365手机下载安装

李太白集作者:李白

📅 08-20 👁️ 4211
手机qq权限设置在哪里(手机qq权限设置在哪里设置)
365bet备用在线

手机qq权限设置在哪里(手机qq权限设置在哪里设置)

📅 07-19 👁️ 8042