为什么 stoi 比没有 -O3 的 stringstream 慢很多?

问题描述 投票:0回答:2

今天我谈论的是 C++11 中的新闻特性,如线程、to_string 和 stoi。

但事实上,这一切在 C++98 中已经成为可能。

然后我决定比较旧库和新闻库:

C++11:

g++ -std=c++11 main.cpp

#include <iostream>
#include <string>
#include <ctime>

using namespace std;

int main()
{
    clock_t tStart = clock();
    string input = "50";

    for (int i = 0; i < 50000; i++)
    {
        int number = stoi(input);
    }

    cout << (double)(clock() - tStart) << endl;
    return 0;
}

C++98

g++ main.cpp

#include <iostream>
#include <string>
#include <sstream>
#include <ctime>

using namespace std;

int main()
{
    clock_t tStart = clock();
    string input = "50";
    stringstream ss;

    for (int i = 0; i < 50000; i++)
    {
        int number;
        ss << input;
        ss >> number;
    }

    cout << (double)(clock() - tStart) << endl;
    return 0;
}

屏幕截图:

Windows 7 轻型服务器:

Ubuntu 14.04:

通过 SSH 的 Slackware Server 14.1:

优化

Windows 7 轻型服务器:

Ubuntu 14.04:

通过 SSH 的 Slackware Server 14.1:

配置:

Windows 7 轻型服务器: Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz

Ubuntu 14.04: Intel(R) Core(TM) i7-2670QM CPU @ 2.20GHz

通过 SSH 的 Slackware Server 14.1: Intel(R) Core(TM) i3-4150 CPU @ 3.50GHz

问题:

stoi 和 stringstream 有什么区别?

为什么以及何时使用字符串库中的新闻函数(stoi、to_string)?

最后... stoi 使用 -O3 速度更快,而 sstream 则不然。那么,-O3 对 stoi 的作用与对 sstream 的作用相比有何不同?

c++ c++11 stringstream c++98
2个回答
8
投票

我刚刚检查了以下内容:

gcc -v:

Using built-in specs.
COLLECT_GCC=x86_64-alt-linux-gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-alt-linux/5/lto-wrapper
Target: x86_64-alt-linux
Configured with: ../configure --host=x86_64-alt-linux --build=x86_64-alt-linux --target=x86_64-alt-linux --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --datadir=/usr/share --includedir=/usr/include --libdir=/usr/lib64 --libexecdir=/usr/libexec --localstatedir=/var/lib --sharedstatedir=/var/lib --mandir=/usr/share/man --infodir=/usr/share/info --disable-dependency-tracking --without-included-gettext --enable-shared --program-suffix=-5 --with-slibdir=/lib64 --with-bugurl=http://bugzilla.altlinux.org --enable-__cxa_atexit --enable-threads=posix --enable-checking=release --with-system-zlib --without-included-gettext --enable-multilib --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --with-arch_32=i586 --with-tune_32=generic --with-multilib-list=m64,m32,mx32 --enable-bootstrap --enable-languages=c,c++,fortran,objc,obj-c++,java,ada,go,lto --enable-plugin --enable-java-awt=gtk --with-native-libdir=/usr/lib64/gcj-5 --with-ecj-jar=/usr/share/java/ecj.jar --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-1.5.0.0/jre --enable-libgcj-multifile --disable-libjava-multilib --enable-java-maintainer-mode
Thread model: posix
gcc version 5.3.1 20151207 (ALT Linux 5.3.1-alt1) (GCC)

代码:

#include <iostream>
#include <string>
#include <chrono>
#include <sstream>

using namespace std;
using namespace chrono;

void stringstream_test(const string& input, int repetitions) {
    stringstream ss;
    auto start = steady_clock::now();
    for (int i = 0; i < repetitions; i++) {
        int number;
        ss << input;
        ss >> number;
    }

    auto end = steady_clock::now();
    auto dur = duration_cast<nanoseconds>(end - start);
    cout << "stringstream_test completed in " << dur.count() << " nanoseconds." << endl;
}

void stoi_test(const string& input, int repetitions) {
    auto start = steady_clock::now();
    for (int i = 0; i < repetitions; i++) {
        int number = stoi(input);
    }
    auto end = steady_clock::now();
    auto dur = duration_cast<nanoseconds>(end - start);
    cout << "stoi_test         completed in " << dur.count() << " nanoseconds." << endl;
}

int main() {
    stringstream_test("50", 500000);
    stoi_test("50", 500000);
    return 0;
}

编译为

c++ -std=c++11 -O3 -o stoi_perf stoi_perf.cc

结果,收到

while true; do ./stoi_perf; done
,重复几次后停止:

stringstream_test completed in 10449080 nanoseconds.
stoi_test         completed in 10437559 nanoseconds.
stringstream_test completed in 9074869 nanoseconds.
stoi_test         completed in 9895661 nanoseconds.
stringstream_test completed in 11516788 nanoseconds.
stoi_test         completed in 12266627 nanoseconds.
stringstream_test completed in 10017085 nanoseconds.
stoi_test         completed in 9468441 nanoseconds.
stringstream_test completed in 9957401 nanoseconds.
stoi_test         completed in 9483004 nanoseconds.
stringstream_test completed in 10069845 nanoseconds.
stoi_test         completed in 9657653 nanoseconds.
stringstream_test completed in 9568359 nanoseconds.
stoi_test         completed in 9162406 nanoseconds.
stringstream_test completed in 9868536 nanoseconds.
stoi_test         completed in 9166439 nanoseconds.
stringstream_test completed in 9059762 nanoseconds.
stoi_test         completed in 11558076 nanoseconds.
stringstream_test completed in 11673084 nanoseconds.
stoi_test         completed in 13432386 nanoseconds.
...

正如您所看到的,两项测试都给出了可比的结果,有时一项测试比另一项测试稍好一些。我的工作站很繁忙(有一个后台进程完全消耗了六个核心中的一两个),但即使在这种情况下,测试结果看起来也令我满意。


0
投票

如果将基准字符串值“50”修改为“5000000”,并使用“gcc -O2”,结果将会改变。可能是因为 stoi 有一个 for 循环。

[root@rjb-101-39 2011]# g++ streamstring_stoi.cpp -O2
[root@rjb-101-39 2011]# ./a.out
stringstream_test completed in 15779245 nanoseconds.
stoi_test         completed in 22976010 nanoseconds.
[root@rjb-101-39 2011]# ./a.out
stringstream_test completed in 14336482 nanoseconds.
stoi_test         completed in 19819919 nanoseconds.
[root@rjb-101-39 2011]# ./a.out
stringstream_test completed in 14542377 nanoseconds.
stoi_test         completed in 18901202 nanoseconds.
[root@rjb-101-39 2011]# ./a.out
stringstream_test completed in 14383620 nanoseconds.
stoi_test         completed in 19766954 nanoseconds.
[root@rjb-101-39 2011]#
© www.soinside.com 2019 - 2024. All rights reserved.