C++ 提高/优化C+中的文件写入速度+;

C++ 提高/优化C+中的文件写入速度+;,c++,performance,usrp,software-defined-radio,uhd,C++,Performance,Usrp,Software Defined Radio,Uhd,我在写文件时遇到了一些问题,即写得不够快 为了说明这一点,我的目标是捕获通过千兆以太网传入的数据流,并将其保存到一个文件中 原始数据以10MS/s的速率输入,然后保存到缓冲区,然后写入文件 以下是守则的相关章节: std::string path = "Stream/raw.dat"; ofstream outFile(path, ios::out | ios::app| ios::binary); if(outFile.is_open()) cout

我在写文件时遇到了一些问题,即写得不够快

为了说明这一点,我的目标是捕获通过千兆以太网传入的数据流,并将其保存到一个文件中

原始数据以10MS/s的速率输入,然后保存到缓冲区,然后写入文件

以下是守则的相关章节:

    std::string path = "Stream/raw.dat";
    ofstream outFile(path, ios::out | ios::app| ios::binary);

    if(outFile.is_open())
        cout << "Yes" << endl;

    while(1)
    {
         rxSamples = rxStream->recv(&rxBuffer[0], rxBuffer.size(), metaData);
         switch(metaData.error_code)
         {

             //Irrelevant error checking...

             //Write data to a file
                std::copy(begin(rxBuffer), end(rxBuffer), std::ostream_iterator<complex<float>>(outFile));
         }
    } 
std::string path=“Stream/raw.dat”;
流输出文件(路径,ios::out | ios::app | ios::binary);
if(outFile.is_open())

cout所以这里的主要问题是,您试图在接收到的线程中写入,这意味着只有在复制完成后才能再次调用recv()。一些意见:

  • 将书写移动到其他线程。这是关于USRP的,所以GNU无线电可能真的是你选择的工具——它本质上是多线程的
  • 您的输出迭代器可能不是性能最好的解决方案。对文件描述符简单地“write()”可能更好,但这是由您决定的性能度量
  • 如果您的硬盘驱动器/文件系统/操作系统/CPU没有达到USRP提供的速度,即使将接收与写入线程分离,那么您也无能为力——获得一个更快的系统
  • 改为尝试写入RAM磁盘

事实上,我不知道你是如何想出
std::copy
方法的。这是一个简单的写作,你肯定会喜欢它,而不是复制;在好的操作系统上,文件I/O通常只需要少一个副本就可以完成,而遍历所有元素的速度可能非常慢。

让我们做一点数学计算

您的样本(显然)属于
std::complex
类型。给定一个(典型的)32位浮点,这意味着每个样本是64位的。在10毫秒/秒的速度下,这意味着原始数据约为每秒80兆字节——这在您可以预期写入桌面(7200 RPM)硬盘驱动器的范围内,但已接近极限(通常约为每秒100-100兆字节左右)


不幸的是,尽管使用了
std::ios::binary
,您实际上是在以文本格式编写数据(因为
std::ostream\u迭代器
基本上是流式的,这是关于USRP的,不是很有趣吗?…纯C指针式的方向可能会更好。如果你知道操作系统的结构,你可能能够更快地访问内存。是的…我使用的是USRP N210。std::copy copy元素明智吗?这是一个常见的mis执行IO时采取。超慢。添加了USRP和软件定义的无线电标签,因为它们适用于此处。无法获得实时处理所需的总体系统性能是一个非常常见的问题。同意,添加更多:将传入数据写入一个或多个大型缓冲区(取决于接收数据和写入文件之间的延迟时间)。创建一个线程,从该缓冲区读取数据并写入文件(以大数据块形式)。此外,尽可能多地使用硬件协助,如DMA。@Thomasmatthew同意,一般来说,较大的数据块=更好的性能,但这也有缺点,即,如果数据块不太大,操作系统可能不会因为处理这些数据的时间过长而忙碌,而在CPU核心稀疏的系统上,操作系统忙碌的时间也会缩短如果文件I/O不能跟上通过网络同时获取数据的速度,它可能会变得至关重要。Linux在多核上的扩展性相当好,所以这实际上只是单核CPU上的一个问题。@ThomasMatthews我按照你的建议切换到了
,这是一个巨大的改进-它还没有溢出。我还增加了sed我的缓冲区大小。@Mlagma很高兴听到这个消息!只要你的应用程序不仅仅是写文件(你也可以用上面提到的示例程序来做),我仍然建议使用多线程。@ThomasMatthews我目前正在开发一个多线程应用程序。实际上,我不会用这个函数编写文件。目前,这只是为了证明概念。我最近刚刚完成了一个多线程缓冲区,用于将示例传递到程序的不同部分,如dem调制等等。不要绕过缓冲。异步或至少在一个单独的线程上执行IO。浪费CPU是不好的,但不管你做什么,都要填充操作系统缓冲区,这样才能保持驱动器的效率。@EliotGillum:正是这样的评论让so最好的贡献者相信,他们最好退出并献花,而不是尝试你有很多朋友,但你个人有责任让世界变得更糟。重读答案的最后一段。继续重读,尽可能多地了解你的评论是完全错误的。残忍永远不会让社区变得更好,不管你有多大的代表性我不认为这太残酷了。我认为这是对事实的观察。“……我的目标是捕获通过千兆以太网传入的数据流,并将其保存到一个文件中。”这并没有表明他会从正在接收的文件内容污染缓存中获益。
uint32_t nItems = std::end(rxBuffer)-std::begin(rxBuffer);
outFile.write((char *)&nItems, sizeof(nItems));
outFile.write((char *)&rxBuffer[0], sizeof(rxBuffer));