繁体   English   中英

Visual C ++-为什么使用unsigned char ifstream读取文件比使用char ifstream慢得多

[英]visual c++ - why is reading a file with an unsigned char ifstream so much slower than using a char ifstream

我一直在使用Visual Studio用C ++读取文件来测试性能,但是我得到了一些我确实不明白的结果。

我的代码如下:

std::vector<unsigned char> Method1(std::string filePath)
{
    std::basic_ifstream<unsigned char> file(filePath, std::ios::binary);

    file.seekg(0, std::ios::end);
    std::streamsize size = file.tellg();
    file.seekg(0, std::ios::beg);

    std::vector<unsigned char> buffer(size);
    file.read(buffer.data(), size);

    return buffer;
}

(我实际上使用uint8_t代替了unsigned char,但是由于它只是一个typedef,因此我在这里使用了后者来更好地说明问题)

我给它一个3mb的文件来读取并使用std :: chrono函数对其计时,这是我的结果:
调试配置-10.2秒
发行配置-98毫秒

调试和发布之间的巨大差异已经引起关注。

因此,我尝试将所有对“ unsigned char”的引用替换为“ char”(std :: basic_ifstream <char>而不是std :: basic_ifstream <unsigned char>等),然后重新运行该程序。
我发现它在调试和发布时都运行了不到3毫秒的时间。

经过多摆弄之后,我意识到了basic_ifstream <unsigned char>是问题所在。 如果我将其他所有内容都保留了下来并将文件更改为basic_ifstream <char>(也带有reinterpret_cast <char *>(buffer.data())),那么它也可以正常工作。

我已经在两台单独的计算机上对此进行了验证,其中一台运行Visual Studio 2015的最新发行版,一台运行Visual Studio 15的Preview 3。

使用unsigned chars时,是否有某种微妙之处使basic_ifstream的性能如此差?

您看到的一些内容几乎肯定是由于缓存。

在3毫秒内读取3 mb的文件意味着您以每秒1000兆字节或每秒8吉比特的速度读取文件(暂时不考虑成帧等)。

SATA 3连接的理论最大速度为每秒6吉比特,但也有8b / 10b编码,因此您希望的最大可见速度为每秒4.8吉比特-仅超过您获得的速度的一半。

真正的驱动器甚至比这更受限制。 典型的旋转硬盘驱动器被限制为每秒约130兆字节。 快速SSD可以将其提高到大约500 MB / s左右。 因此,除非您为RAID配置了至少16个可用的快速SSD,否则您不会在3毫秒内从磁盘读取3 mb的文件(并且RAID控制器会自己添加一些开销,因此要可靠地获得这种速度) ,则可能需要更多(例如18或20个快速SSD)。

下一个瓶颈将是PCIe总线。 PCIe 3.0的理论上最大最大带宽为每通道985 MB / s,因此您的RAID控制器将需要使用大约9条通道来快速传输数据-如果超过8条,则下一步(可能)是16.大多数RAID控制器仅使用4条通道,其中相当一部分也仅使用PCIe第2代。 这使他们远远没有达到您所谈论的带宽(大约四分之一的带宽)。 我所知道的最快的RAID控制器(8000系列Adaptec)都使用8通道PCIe板。 我不知道任何16通道PCIe RAID控制器。

显而易见的替代方法是您从主内存中读取了大量的数据。 大多数操作系统都会在主内存中缓存数据,因此,如果您连续两次(相对)快速读取相同的数据两次,那么第二次您将从内存中读取数据,而不是从磁盘上传输数据。

换句话说,第一次读取数据时,就有时间从实际的存储设备读取数据。 随后尝试读取(第一后很快就会碰巧)可从主内存中缓存检索数据,通常给人更快的访问(这就是为什么他们在第一时间做缓存)。

现在,几乎不可能猜测您看到的差异到底有多少可以归因于代码中的差异以及缓存有多少。但是,鉴于您拥有的带宽,没有真正的问题要问:您看到的内容一定是由于缓存所致,因为您几乎不可能以如此快的速度从存储设备中读取数据。

时间上的差异是因为在调试期间Visual Studio运行的代码未经过优化。 当编译并运行以进行发布时,它会执行一些底层技巧来优化代码。 有关更多详细信息,请参见此链接 ,以及本网站

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM