我正试图将大量的数据写入我的SSD(固态硬盘)。我说的巨大是指80GB。

我在网上寻找解决方案,但我想到的最好的办法是:

#include <fstream>
const unsigned long long size = 64ULL*1024ULL*1024ULL;
unsigned long long a[size];
int main()
{
    std::fstream myfile;
    myfile = std::fstream("file.binary", std::ios::out | std::ios::binary);
    //Here would be some error handling
    for(int i = 0; i < 32; ++i){
        //Some calculations to fill a[]
        myfile.write((char*)&a,size*sizeof(unsigned long long));
    }
    myfile.close();
}

使用Visual Studio 2010编译,完全优化,在Windows7下运行,该程序最大可达20MB/s左右。真正困扰我的是,Windows可以以150MB/s到200MB/s之间的速度将文件从另一个SSD复制到这个SSD。至少快7倍。这就是为什么我认为我应该能跑得更快。

有什么办法可以加快我的写作速度吗?


当前回答

尝试使用内存映射文件。

其他回答

按顺序尝试以下方法:

Smaller buffer size. Writing ~2 MiB at a time might be a good start. On my last laptop, ~512 KiB was the sweet spot, but I haven't tested on my SSD yet. Note: I've noticed that very large buffers tend to decrease performance. I've noticed speed losses with using 16-MiB buffers instead of 512-KiB buffers before. Use _open (or _topen if you want to be Windows-correct) to open the file, then use _write. This will probably avoid a lot of buffering, but it's not certain to. Using Windows-specific functions like CreateFile and WriteFile. That will avoid any buffering in the standard library.

您是否可以使用FILE*来代替,并衡量您所获得的性能? 有几个选项是使用fwrite/write而不是fstream:

#include <stdio.h>

int main ()
{
  FILE * pFile;
  char buffer[] = { 'x' , 'y' , 'z' };
  pFile = fopen ( "myfile.bin" , "w+b" );
  fwrite (buffer , 1 , sizeof(buffer) , pFile );
  fclose (pFile);
  return 0;
}

如果你决定使用write,试试类似的方法:

#include <unistd.h>
#include <fcntl.h>

int main(void)
{
    int filedesc = open("testfile.txt", O_WRONLY | O_APPEND);

    if (filedesc < 0) {
        return -1;
    }

    if (write(filedesc, "This will be output to testfile.txt\n", 36) != 36) {
        write(2, "There was an error writing to testfile.txt\n", 43);
        return -1;
    }

    return 0;
}

我还建议你研究一下内存映射。这可能就是你的答案。有一次我不得不处理一个20GB的文件,把它存储在数据库中,而这个文件甚至没有打开。因此,解决方案是利用内存映射。不过我在Python中做到了。

我发现std::stream/FILE/device之间没有区别。 在缓冲和非缓冲之间。

还要注意:

SSD驱动器“倾向于”变慢(更低的传输速率),因为它们被填满了。 SSD驱动器“倾向于”变慢(更低的传输速率),因为它们变老了(因为没有工作位)。

我看到代码在63秒内运行。 因此传输速率为:260M/s(我的SSD看起来比你的快一点)。

64 * 1024 * 1024 * 8 /*sizeof(unsigned long long) */ * 32 /*Chunks*/

= 16G
= 16G/63 = 260M/s

我从std::fstream移动到FILE*没有增加。

#include <stdio.h>

using namespace std;

int main()
{
    
    FILE* stream = fopen("binary", "w");

    for(int loop=0;loop < 32;++loop)
    {
         fwrite(a, sizeof(unsigned long long), size, stream);
    }
    fclose(stream);

}

因此,c++流的工作速度与底层库所允许的一样快。

但我认为将操作系统与构建在操作系统之上的应用程序进行比较是不公平的。应用程序不能做任何假设(它不知道驱动器是SSD),因此使用操作系统的文件机制进行传输。

而操作系统不需要做任何假设。它可以告诉所涉及的驱动器的类型,并使用最佳的技术来传输数据。在这种情况下,是直接内存到内存的传输。试着写一个程序,把80G从内存的一个位置复制到另一个位置,看看有多快。

Edit

我修改了我的代码,以使用较低级别的调用: 没有缓冲。

#include <fcntl.h>
#include <unistd.h>


const unsigned long long size = 64ULL*1024ULL*1024ULL;
unsigned long long a[size];
int main()
{
    int data = open("test", O_WRONLY | O_CREAT, 0777);
    for(int loop = 0; loop < 32; ++loop)
    {   
        write(data, a, size * sizeof(unsigned long long));
    }   
    close(data);
}

这没什么区别。

注意:我的驱动器是SSD驱动器,如果你有一个普通的驱动器,你可能会看到上面两种技术之间的区别。但正如我所期望的那样,非缓冲和缓冲(当写入大于缓冲区大小的大块时)没有区别。

编辑2:

你试过用c++复制文件的最快方法吗

int main()
{
    std::ifstream  input("input");
    std::ofstream  output("ouptut");

    output << input.rdbuf();
}

我建议尝试文件映射。我过去在UNIX环境中使用过mmapin,它所能实现的高性能给我留下了深刻的印象

尝试使用内存映射文件。