Mla*_*gma 10 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 << "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));
}
}
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是将样本写入文件需要很长时间.大约一秒钟后,发送样本的设备报告其缓冲区已溢出.在对代码进行一些快速分析之后,几乎所有的执行时间都花在了std::copy(...)
(确切地说是99.96%的时间).如果我删除这一行,我可以运行该程序几个小时而不会遇到任何溢出.
也就是说,我对如何提高写入速度感到困惑.我已经浏览了这个网站上的几个帖子,看起来最常见的建议(关于速度)是实现文件写入,就像我已经完成的那样 - 通过使用std::copy
.
如果它有用,我在Ubuntu x86_64上运行这个程序.任何建议,将不胜感激.
Mar*_*ler 13
所以这里的主要问题是你尝试在收到的同一个线程中写入,这意味着你的recv()只能在复制完成后再次调用.一些观察:
事实上,我不知道你是如何想出这种std::copy
方法的.UHD附带的rx_samples_to_file示例通过简单的写入来完成此操作,您绝对应该支持复制; 在优秀的操作系统上,文件I/O通常可以减少一个副本,并且迭代所有元素可能非常慢.
让我们做一些数学运算。
您的样品(显然)是类型 std::complex<std::float>
. 给定一个(典型的)32 位浮点数,这意味着每个样本是 64 位。在 10 MS/s 时,这意味着原始数据大约为每秒 80 兆字节——这在您可以预期写入台式机 (7200 RPM) 硬盘驱动器的范围内,但已经相当接近极限(通常约为 100 -100 兆字节/秒左右)。
不幸的是,尽管std::ios::binary
,您实际上是以文本格式写入数据(因为std::ostream_iterator
基本上是这样stream << data;
)。
这不仅会损失一些精度,还会增加数据的大小,至少通常如此。确切的增加量取决于数据——一个小的整数值实际上可以减少数据量,但对于任意输入,接近 2:1 的大小增加是相当普遍的。随着 2:1 的增加,您的输出数据现在大约为 160 兆字节/秒——这比大多数硬盘驱动器可以处理的速度要快。
改进的明显起点是以二进制格式写入数据:
uint32_t nItems = std::end(rxBuffer)-std::begin(rxBuffer);
outFile.write((char *)&nItems, sizeof(nItems));
outFile.write((char *)&rxBuffer[0], sizeof(rxBuffer));
Run Code Online (Sandbox Code Playgroud)
目前我sizeof(rxBuffer)
假设它是一个真正的数组。如果它实际上是一个指针或向量,则必须计算正确的大小(您想要的是要写入的总字节数)。
我还注意到,就目前的情况而言,您的代码有一个更严重的问题:由于它在写入数据时没有指定元素之间的分隔符,因此写入数据时不会有任何将一项与下一个。这意味着如果你写了两个值(例如)1
and 0.2
,你读回的不会是1
and 0.2
,而是一个值10.2
。向文本输出添加分隔符会为已经失败的进程增加更多开销(大约增加 15% 的数据),因为它生成了太多数据。
以二进制格式写入意味着每个浮点数将精确消耗 4 个字节,因此不需要分隔符来正确读回数据。
之后的下一步将下降到较低级别的文件 I/O 例程。根据情况,这可能会或可能不会产生太大差异。在 Windows 上,您可以指定FILE_FLAG_NO_BUFFERING
何时打开带有CreateFile
. 这意味着对该文件的读写基本上会绕过缓存并直接进入磁盘。
在您的情况下,这可能是一个胜利——以 10 MS/s 的速度,在您重新读取相同的数据之前,您可能会用完缓存空间很长一段时间。在这种情况下,让数据进入缓存几乎没有任何好处,但会花费一些数据来将数据复制到缓存,然后稍后再将其复制到磁盘。更糟糕的是,所有这些数据很可能会污染缓存,因此它不再存储更有可能从缓存中受益的其他数据。
归档时间: |
|
查看次数: |
4440 次 |
最近记录: |