为什么这种逐行文件读取在 c++ 中比在 Python 中慢得多

How can this line-by-line file reading be much slower in c++ than in Python?

本文关键字:Python c++ 逐行 文件 读取 为什么      更新时间:2023-10-16

我有一个2GB的文件。平均一行有 15 个字符(最多 50 个字符(。使用时:

#include <iostream>
#include <fstream>
#include <string>
void main()
{
    std::ifstream input("myfile.txt");
    std::string line;
    while (std::getline(input, line))
    {
    }
    return;
}

它需要 ~ 320 秒,而这个 Python 代码:

with open('myfile.txt', mode='r') as f:
    for l in f:
        semicolonpresent = ';' in l        # do anything here, not important

不到一分钟。

我使用的C++版本有什么问题?

注意:我已经尝试了很多次,每次都是在重新启动后,或者在以前的多次运行之后(因此它可能在I/O缓存中(,但我总是得到这样的数量级。

注意2:我在Windows 7/64上编译了C++代码,使用:

call "C:Program Files (x86)Microsoft Visual Studio 12.0VCvcvarsall.bat" x86
cl main.cpp

在我的测试中,C++并不比Python慢。在大型二进制文件中,它们大致相同。

我稍微修改了您的代码,以提供我认为应该是准确的时间。

蟒蛇代码

import sys
import time 
start = time.time()
sum = 0
with open(sys.argv[1], mode='r') as f:
    for l in f:
        sum = sum + 1
end = time.time()
print "(", sum, ")", (end - start), "secs"

C++代码

    auto start = std::chrono::steady_clock::now();
    std::ifstream ifs(argv[1]);
    std::string line;
    unsigned sum = 0;
    while(std::getline(ifs, line))
        ++sum;
    auto end = std::chrono::steady_clock::now();
    auto time = double(std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count());
    OUT("( " << sum << " ) " << (time / 1000.0) << " secs");

处理7.1 GiB二进制视频文件可提供:

Python: ( 32547618 ) 62.9722070694 secs
C++   : ( 32547618 ) 63.368 secs

C++代码是在GCC v7.2上使用以下标志编译的:

g++ -std=c++17 -O3 ...

相比之下,未优化的代码运行在68.541 secs

void main C++无效。也不是main()的空return.此外,启用优化后,您的while循环将被优化。话虽如此...

如果打开优化,您应该会注意到速度有所提高。但是,C++中的流很慢。这对C++世界来说不是新闻。那么为什么Python要快得多呢?两者并不真正等同。Python 是用 C 编写的,并在内部委托给 C 库函数。此外,Python 很可能提前分配一个缓冲区并一次性复制缓冲区。如果您想在C++中执行类似操作:

std::ifstream ifs(filename);
auto end = ifs.tellg();
ifs.seekg(0, std::ios::beg);
auto beg = ifs.tellg();
std::string buffer;
buffer.reserve(end - beg);
std::copy(std::istreambuf_iterator<char>(ifs),
          std::istreambuf_iterator<char>(),
          buffer.begin());

(部分( 答案:

正如许多人在评论中提到的,cl优化有助于:

cl /Ox helloworld1.cpp

将运行时间除以 6!