SDRデバイスからバッファを高速で取り込むツールを作成しました(1秒間に1000万の複合サンプル(サンプルは短いタイプです))。しかし、私が書いたコードでは、書かれたことを振り返るたびに、私は小さな塊を見逃しています。C++での高速バッファリング
私がこの問題を軽減しようとしたのは、同じサイズの2つのバッファを使用し、それらの間をスワップしてサンプルを紛失しないようにすることです。バッファを交換してバックバッファ(サンプルサイズの3倍のサイズ)にサンプルをオフロードし、必要に応じて新しいスレッドを呼び出して新しいデータをディスクに書き込むときは、チャンクがなくなります。
SDR装置自体は、2016年のような奇妙なものとして独自の内部バッファサイズを通知し、それは、サンプルの実部と虚アレイへの2つのポインタを与えます。明らかに、私はこのサンプルレートでこのような小さな配列のオーバーヘッドを避けたいので、スワップバッファを65536と大きなサイズで実装することで、うまくいけばこのような問題を避けることができます。
私はピンが欠落しているチャンクがより頻繁になるバッファ私はスワップのサイズを小さくするときので、コールバック関数で最も可能性が高いと問題点を指摘しています。
私はこれを間違った方法で行っているのですか、私の解決策に欠けているものがあるか、何か正しく書かれていませんか?
私はそれが故にデータ速度のこの種のMEMMOVEとmemcpyのための必要性のために遅すぎるという理由だけで、可能な限り標準libaryを避けてきました。唯一の例外は、バッファポインタのスワッピングとスレッドの作成です。 IQTypeは
IQType<short>* bufferA;
IQType<short>* bufferB;
:
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:SDRサンプルデータをアンロード
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デバイスコールバック関数としてのバッファをスワップ
が実装されています機能:
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を使っていましたが、30ミリオンのサンプルが5秒間保存されました。 memmoveはこれを何百回も高速化します。 Justyは、バックバッファのデータを記録する以外のことを明確にするために、バックバッファは、記録されたデータの最後の3秒を観察するためにも使用されます。キューと同様に扱われますが、バックボッファのサイズまでの任意の位置と長さを見るオプションがあります。 – Gelion