我一直在编写一个工具,它可以从SDR设备以高速缓存(每秒1000万个复杂采样(样本是短类型))。但是,随着我写的代码,每当我回头看写的内容时,我都会看到一些小块。C++中的高速缓冲
我试图缓解这个问题的方法是使用两个相同大小的缓冲区并在它们之间交换以避免丢失任何样本。每当我经历交换缓冲区并将样本卸载到后台缓冲区(其大小是采样速率的3倍)并且如果需要时调用新线程以将新数据写入到磁盘时,块会丢失。
SDR设备本身将自己的内部缓冲区大小通告为2016年的奇怪事物,它给出了实数和虚数采样数组的两个指针。很明显,我想避免这样的小数组在这个采样率上的开销,所以通过实现更大尺寸的交换缓冲区65536,希望我希望能避免这样的问题,但无济于事。
我已经指出问题最有可能在回调函数,因为当我减少交换缓冲区的大小失踪块变得更加频繁。
我是否正在做这个错误的方法,或者有更明显的东西在我的解决方案中缺少,或者我没有正确书写一些东西?
我尽可能地避免了标准库,因为它对于这种数据速度来说太慢了,因此需要memmove和memcpy。唯一的例外是缓冲区指针交换和创建线程。
交换缓冲器被实现为:
IQType<short>* bufferA;
IQType<short>* bufferB;
IQType是:
template <class T> class IQType {
public:
T inPhaseValue;
T quadraturePhaseValue;
IQType() : inPhaseValue(0), quadraturePhaseValue(0){};
IQType(T i, T q) : inPhaseValue(i), quadraturePhaseValue(q){};
};
SDR装置回调函数卸载SDR的示例数据:
void MiricsDataSource::newSamplesCallBack(short *xi, short *xq, unsigned int firstSampleNum, int grChanged, int rfChanged, int fsChanged, unsigned int numSamples, unsigned int reset, void *cbContext) {
MiricsDataSource* mirCtx = static_cast<MiricsDataSource*>(cbContext);
for (int i = 0; i < numSamples; ++i)
{
mirCtx->bufferA[mirCtx->bufferCount] = IQType<short>(xi[i],xq[i]);
mirCtx->bufferCount++;
if(mirCtx->bufferCount == mirCtx->bufferSize-1) {
std::swap(mirCtx->bufferA,mirCtx->bufferB);
mirCtx->owner->backBuffer->write(mirCtx->bufferB,mirCtx->bufferSize);
mirCtx->bufferCount = 0;
}
}
}
后备缓冲写和相关t_write功能:
void BackBuffer::write(const IQType<short>* buff, size_t bLength) {
std::thread dumpThread(&BackBuffer::t_write,this,buff,bLength);
dumpThread.detach();
}
void BackBuffer::t_write(const IQType<short>* buff, size_t bLength) {
std::lock_guard<std::mutex> lck (bufferMutex);
memmove(&backBuffer[0],(&backBuffer[0])+bLength,(sizeof(IQType<short>*)*(length-bLength)));
memcpy(&backBuffer[length-bLength],buff,(sizeof(IQType<short>*)*(bLength)));
if(dumpToFile) {
IQType<short>* toWrite = new IQType<short>[bLength];
memcpy(toWrite,buff,(sizeof(IQType<short>*)*(bLength)));
strmDmpMgr->write(toWrite,bLength);
}
}
'我尽可能地避免了标准库,因为它对于这种数据速度来说太慢了,因此对memmove和memcpy的需求我只是不明白当标准库当类型在你的情况下是微不足道的时候会执行memcpy/memmove。如果你真的没有测量它,那么请删除该声明。 – Arunmu
“我尽量避免使用标准库,因此需要[标准库中的函数]”似乎有点矛盾。 – user2079303
最初我使用std :: rotate来移动backbuffer,但这样做需要5秒钟才能存储3000万个样本。 memmove做这几百倍更快。只是为了澄清我用backbuffer中的数据做其他事情而不是记录。后缓冲器也用于观察记录数据的最后3秒。它的处理方式与队列类似,但可以选择查看任何位置和任何长度,直到backbuffer的大小。 – Gelion