2013-07-31 37 views
4

我正在使用Windows 7中的VS2012(64位8核)从本地硬盘读取.csv文件。在C++中,如何使用多个线程读取一个文件?

我正在阅读的文件有50,000多行,每行有200多个属性,因此读取数据并将它们提供给相应的变量非常耗时。因此,我想知道是否可以用多线程加速它,每个线程读取文件的一部分。

我已经google了一下,发现有人说,由于硬盘不是多线程,使用多线程来做到这一点将会实际上慢下来这是真的吗?

如果可以读取多个线程的文件,任何人都可以给我一个我可以学习的例子吗?

此外,是否有可能将明确分配给CPU内核的线程或任务?

还有一个最后的问题:我用Python读了同一个文件,并且在几秒钟内就完成了。 我可以知道为什么Python的读取速度比C++快吗?

+2

在C++中使用STL文件缓冲的一个简单的示例一般地从文件中的确会慢下来发言多线程读数。该程序可能是多线程的,但考虑磁盘控制器和读/写磁头......可以构造此规则的例外情况,例如并行文件系统(您知道是否有),计算很多文件读取块之间的处理,以及其他一些情况。 –

+0

您可以让一个线程读取文件,然后将块传递给多个解析器线程。理想情况下,您有一个用于保存数据的并发集合,因此工作线程可以快速有效地将解析结果插入(假设您需要将所有数据放在内存中的一个数据结构中)。 – hyde

+0

除非在读取数据后处理数据的计算量非常大,否则使用多线程读取文件将无济于事。没有看到你如何在Python和C++中实现文件读取,很难知道为什么你在C++中看到更糟的性能。我猜你正在使用C++ API不正确或很差。 – Kylos

回答

2

读取文件需要在任何语言或操作系统下创建一个系统调用,这意味着调用底层操作系统,并等待它将文件内容放入内存中(假设您通过操作系统安全检查和所有这些)。多线程文件读取确实会减慢你的速度,因为你会制造更多的系统调用,使你不能执行程序并将控制权交给操作系统。

因此,最好的建议是海德的 - 如果需要的话,也许将文件解析到多个线程。如果你能够在几秒钟内解析一个很大的文件,我会说它并不值得。例如,如果您正在运行图形应用程序,那么您肯定希望为文件加载保留一个单独的线程,以免冻结您的用户界面。

在速度问题上,我猜想有两个主要问题。首先,我怀疑python默认通过内存缓冲区读取它的文件,这将加速执行。如果你可以缓冲你的文件读取(这样你可以减少系统调用),你可能会看到一些性能上的提升。另一个问题是你在Python和C++中使用哪些数据结构来加载/解析数据。在不知道代码的情况下,我无法提出任何具体的建议,但花一点时间研究/思考适用于您的程序的不同数据结构可能会有所帮助。请记住,Python和C++的数据结构具有非常不同的性能配置文件,所以在Python中运行良好的一个可能是C++中更差的选择。

编辑:http://www.cplusplus.com/reference/

// read a file into buffer - sgetn() example 
#include <iostream>  // std::cout, std::streambuf, std::streamsize 
#include <fstream>  // std::ifstream 

int main() { 
    char* contents; 
    std::ifstream istr ("test.txt"); 

    if (istr) { 
    std::streambuf * pbuf = istr.rdbuf(); 
    std::streamsize size = pbuf->pubseekoff(0,istr.end); 
    pbuf->pubseekoff(0,istr.beg);  // rewind 
    contents = new char [size]; 
    pbuf->sgetn (contents,size); 
    istr.close(); 
    std::cout.write (contents,size); 
    } 
    return 0; 
} 
+0

嗨,最大。非常感谢你的回答。这真的很有启发性。你能给我一个简单的例子,告诉我如何设置一个读缓冲区?它是否必须降到硬件级别?非常感谢。 – ChangeMyName

+0

假设你使用的是C++ STL,你可以在这里看看std :: filebuf的文档:http://www.cplusplus.com/reference/fstream/filebuf/ –

+0

这种寻求和回溯的方法是正如人们抱怨的那样,微软的“bcp”不能用于纯文件以外的任何其他功能,作为一个附注。你可能喜欢使用'std :: vector <>'而不是普通的'char *'数组,这里没有什么好的理由使用后者。 –