Try not to use atomics in performance code

This commit is contained in:
vsonnier 2017-09-22 22:23:34 +02:00
parent aec0100f78
commit 927d727a16
6 changed files with 135 additions and 82 deletions

View File

@ -48,7 +48,15 @@ class ReBuffer {
typedef typename std::shared_ptr<BufferType> ReBufferPtr; typedef typename std::shared_ptr<BufferType> ReBufferPtr;
public: public:
//Virtual destructor to assure correct freeing of all descendants.
virtual ~ReBuffer() {
//nothing
}
//constructor
ReBuffer(std::string bufferId) : bufferId(bufferId) { ReBuffer(std::string bufferId) : bufferId(bufferId) {
//nothing
} }
/// Return a new ReBuffer_ptr usable by the application. /// Return a new ReBuffer_ptr usable by the application.

View File

@ -21,8 +21,8 @@ std::map<int, std::thread *> AudioThread::deviceThread;
AudioThread::AudioThread() : IOThread(), AudioThread::AudioThread() : IOThread(),
currentInput(nullptr), inputQueue(nullptr), nBufferFrames(1024), sampleRate(0) { currentInput(nullptr), inputQueue(nullptr), nBufferFrames(1024), sampleRate(0) {
audioQueuePtr.store(0); audioQueuePtr = 0;
underflowCount.store(0); underflowCount = 0;
active.store(false); active.store(false);
outputDevice.store(-1); outputDevice.store(-1);
gain = 1.0; gain = 1.0;

View File

@ -92,13 +92,13 @@ public:
static void setDeviceSampleRate(int deviceId, int sampleRate); static void setDeviceSampleRate(int deviceId, int sampleRate);
//fields below, only to be used by other AudioThreads ! //fields below, only to be used by other AudioThreads !
std::atomic_uint underflowCount; size_t underflowCount;
//protected by m_mutex //protected by m_mutex
std::vector<AudioThread *> boundThreads; std::vector<AudioThread *> boundThreads;
AudioThreadInputQueuePtr inputQueue; AudioThreadInputQueuePtr inputQueue;
AudioThreadInputPtr currentInput; AudioThreadInputPtr currentInput;
std::atomic_uint audioQueuePtr; size_t audioQueuePtr;
std::atomic<float> gain; float gain;
private: private:

View File

@ -20,11 +20,11 @@ SpectrumVisualProcessor::SpectrumVisualProcessor() : outputBuffers("SpectrumVisu
fftLastData = nullptr; fftLastData = nullptr;
fftPlan = nullptr; fftPlan = nullptr;
is_view.store(false); is_view = false;
fftSize.store(0); fftSize = 0;
centerFreq.store(0); centerFreq = 0;
bandwidth.store(0); bandwidth = 0;
hideDC.store(false); hideDC = false;
freqShifter = nco_crcf_create(LIQUID_NCO); freqShifter = nco_crcf_create(LIQUID_NCO);
shiftFrequency = 0; shiftFrequency = 0;
@ -32,14 +32,14 @@ SpectrumVisualProcessor::SpectrumVisualProcessor() : outputBuffers("SpectrumVisu
fft_ceil_ma = fft_ceil_maa = 100.0; fft_ceil_ma = fft_ceil_maa = 100.0;
fft_floor_ma = fft_floor_maa = 0.0; fft_floor_ma = fft_floor_maa = 0.0;
fft_floor_peak = 0.0; fft_floor_peak = 0.0;
desiredInputSize.store(0); desiredInputSize = 0;
fft_average_rate = 0.65f; fft_average_rate = 0.65f;
scaleFactor.store(1.0); scaleFactor = 1.0;
fftSizeChanged.store(false); fftSizeChanged = false;
newFFTSize.store(0); newFFTSize = 0;
lastView = false; lastView = false;
peakHold.store(false); peakHold = false;
peakReset.store(false); peakReset = false;
} }
@ -48,75 +48,93 @@ SpectrumVisualProcessor::~SpectrumVisualProcessor() {
} }
bool SpectrumVisualProcessor::isView() { bool SpectrumVisualProcessor::isView() {
return is_view.load();
std::lock_guard < std::mutex > busy_lock(busy_run);
return is_view;
} }
void SpectrumVisualProcessor::setView(bool bView) { void SpectrumVisualProcessor::setView(bool bView) {
std::lock_guard < std::mutex > busy_lock(busy_run); std::lock_guard < std::mutex > busy_lock(busy_run);
is_view.store(bView);
is_view = bView;
} }
void SpectrumVisualProcessor::setView(bool bView, long long centerFreq_in, long bandwidth_in) { void SpectrumVisualProcessor::setView(bool bView, long long centerFreq_in, long bandwidth_in) {
std::lock_guard < std::mutex > busy_lock(busy_run); std::lock_guard < std::mutex > busy_lock(busy_run);
is_view.store(bView); is_view = bView;
bandwidth.store(bandwidth_in); bandwidth = bandwidth_in;
centerFreq.store(centerFreq_in); centerFreq = centerFreq_in;
} }
void SpectrumVisualProcessor::setFFTAverageRate(float fftAverageRate) { void SpectrumVisualProcessor::setFFTAverageRate(float fftAverageRate) {
std::lock_guard < std::mutex > busy_lock(busy_run); std::lock_guard < std::mutex > busy_lock(busy_run);
this->fft_average_rate.store(fftAverageRate);
this->fft_average_rate = fftAverageRate;
} }
float SpectrumVisualProcessor::getFFTAverageRate() { float SpectrumVisualProcessor::getFFTAverageRate() {
return this->fft_average_rate.load();
std::lock_guard < std::mutex > busy_lock(busy_run);
return this->fft_average_rate;
} }
void SpectrumVisualProcessor::setCenterFrequency(long long centerFreq_in) { void SpectrumVisualProcessor::setCenterFrequency(long long centerFreq_in) {
std::lock_guard < std::mutex > busy_lock(busy_run); std::lock_guard < std::mutex > busy_lock(busy_run);
centerFreq.store(centerFreq_in);
centerFreq = centerFreq_in;
} }
long long SpectrumVisualProcessor::getCenterFrequency() { long long SpectrumVisualProcessor::getCenterFrequency() {
return centerFreq.load();
std::lock_guard < std::mutex > busy_lock(busy_run);
return centerFreq;
} }
void SpectrumVisualProcessor::setBandwidth(long bandwidth_in) { void SpectrumVisualProcessor::setBandwidth(long bandwidth_in) {
std::lock_guard < std::mutex > busy_lock(busy_run); std::lock_guard < std::mutex > busy_lock(busy_run);
bandwidth.store(bandwidth_in);
bandwidth = bandwidth_in;
} }
long SpectrumVisualProcessor::getBandwidth() { long SpectrumVisualProcessor::getBandwidth() {
return bandwidth.load();
std::lock_guard < std::mutex > busy_lock(busy_run);
return bandwidth;
} }
void SpectrumVisualProcessor::setPeakHold(bool peakHold_in) { void SpectrumVisualProcessor::setPeakHold(bool peakHold_in) {
if (peakHold.load() && peakHold_in) { std::lock_guard < std::mutex > busy_lock(busy_run);
peakReset.store(PEAK_RESET_COUNT);
if (peakHold && peakHold_in) {
peakReset = PEAK_RESET_COUNT;
} else { } else {
peakHold.store(peakHold_in); peakHold = peakHold_in;
peakReset.store(1); peakReset = 1;
} }
} }
bool SpectrumVisualProcessor::getPeakHold() { bool SpectrumVisualProcessor::getPeakHold() {
return peakHold.load();
std::lock_guard < std::mutex > busy_lock(busy_run);
return peakHold;
} }
int SpectrumVisualProcessor::getDesiredInputSize() { int SpectrumVisualProcessor::getDesiredInputSize() {
return desiredInputSize.load(); std::lock_guard < std::mutex > busy_lock(busy_run);
return desiredInputSize;
} }
void SpectrumVisualProcessor::setup(unsigned int fftSize_in) { void SpectrumVisualProcessor::setup(unsigned int fftSize_in) {
@ -157,27 +175,37 @@ void SpectrumVisualProcessor::setup(unsigned int fftSize_in) {
fft_destroy_plan(fftPlan); fft_destroy_plan(fftPlan);
} }
fftPlan = fft_create_plan(fftSizeInternal, fftInput, fftOutput, LIQUID_FFT_FORWARD, 0); fftPlan = fft_create_plan(fftSizeInternal, fftInput, fftOutput, LIQUID_FFT_FORWARD, 0);
} }
void SpectrumVisualProcessor::setFFTSize(unsigned int fftSize_in) { void SpectrumVisualProcessor::setFFTSize(unsigned int fftSize_in) {
//then get the busy_lock
std::lock_guard < std::mutex > busy_lock(busy_run);
if (fftSize_in == fftSize) { if (fftSize_in == fftSize) {
return; return;
} }
newFFTSize = fftSize_in; newFFTSize = fftSize_in;
fftSizeChanged.store(true); fftSizeChanged = true;
} }
unsigned int SpectrumVisualProcessor::getFFTSize() { unsigned int SpectrumVisualProcessor::getFFTSize() {
if (fftSizeChanged.load()) {
//then get the busy_lock
std::lock_guard < std::mutex > busy_lock(busy_run);
if (fftSizeChanged) {
return newFFTSize; return newFFTSize;
} }
return fftSize.load(); return fftSize;
} }
void SpectrumVisualProcessor::setHideDC(bool hideDC) { void SpectrumVisualProcessor::setHideDC(bool hideDC) {
this->hideDC.store(hideDC);
std::lock_guard < std::mutex > busy_lock(busy_run);
this->hideDC = hideDC;
} }
@ -189,11 +217,20 @@ void SpectrumVisualProcessor::process() {
return; return;
} }
if (fftSizeChanged.load()) { bool executeSetup = false;
setup(newFFTSize);
fftSizeChanged.store(false);
}
{ // scoped lock here
std::lock_guard < std::mutex > busy_lock(busy_run);
if (fftSizeChanged) {
executeSetup = true;
fftSizeChanged = false;
}
}
if (executeSetup) {
setup(newFFTSize);
}
DemodulatorThreadIQDataPtr iqData; DemodulatorThreadIQDataPtr iqData;
if (!input->pop(iqData, HEARTBEAT_CHECK_PERIOD_MICROS)) { if (!input->pop(iqData, HEARTBEAT_CHECK_PERIOD_MICROS)) {
@ -204,12 +241,13 @@ void SpectrumVisualProcessor::process() {
return; return;
} }
//then get the busy_lock //then get the busy_lock for the rest of the processing.
std::lock_guard < std::mutex > busy_lock(busy_run); std::lock_guard < std::mutex > busy_lock(busy_run);
bool doPeak = peakHold.load() && (peakReset.load() == 0); bool doPeak = peakHold && (peakReset == 0);
if (fft_result.size() != fftSizeInternal) { if (fft_result.size() != fftSizeInternal) {
if (fft_result.capacity() < fftSizeInternal) { if (fft_result.capacity() < fftSizeInternal) {
fft_result.reserve(fftSizeInternal); fft_result.reserve(fftSizeInternal);
fft_result_ma.reserve(fftSizeInternal); fft_result_ma.reserve(fftSizeInternal);
@ -223,9 +261,9 @@ void SpectrumVisualProcessor::process() {
fft_result_peak.resize(fftSizeInternal); fft_result_peak.resize(fftSizeInternal);
} }
if (peakReset.load() != 0) { if (peakReset != 0) {
peakReset--; peakReset--;
if (peakReset.load() == 0) { if (peakReset == 0) {
for (unsigned int i = 0, iMax = fftSizeInternal; i < iMax; i++) { for (unsigned int i = 0, iMax = fftSizeInternal; i < iMax; i++) {
fft_result_peak[i] = fft_floor_maa; fft_result_peak[i] = fft_floor_maa;
} }
@ -242,7 +280,7 @@ void SpectrumVisualProcessor::process() {
bool newResampler = false; bool newResampler = false;
int bwDiff = 0; int bwDiff = 0;
if (is_view.load()) { if (is_view) {
if (!iqData->sampleRate) { if (!iqData->sampleRate) {
return; return;
@ -256,7 +294,7 @@ void SpectrumVisualProcessor::process() {
size_t desired_input_size = fftSizeInternal / resamplerRatio; size_t desired_input_size = fftSizeInternal / resamplerRatio;
this->desiredInputSize.store(desired_input_size); this->desiredInputSize = desired_input_size;
if (iqData->data.size() < desired_input_size) { if (iqData->data.size() < desired_input_size) {
// std::cout << "fft underflow, desired: " << desired_input_size << " actual:" << input->data.size() << std::endl; // std::cout << "fft underflow, desired: " << desired_input_size << " actual:" << input->data.size() << std::endl;
@ -270,7 +308,7 @@ void SpectrumVisualProcessor::process() {
shiftFrequency = centerFreq - iqData->frequency; shiftFrequency = centerFreq - iqData->frequency;
nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) iqData->sampleRate))); nco_crcf_set_frequency(freqShifter, (2.0 * M_PI) * (((double) abs(shiftFrequency)) / ((double) iqData->sampleRate)));
if (is_view.load()) { if (is_view) {
long freqDiff = shiftFrequency - lastShiftFrequency; long freqDiff = shiftFrequency - lastShiftFrequency;
if (lastBandwidth!=0) { if (lastBandwidth!=0) {
@ -294,7 +332,7 @@ void SpectrumVisualProcessor::process() {
} }
} }
} }
peakReset.store(PEAK_RESET_COUNT); peakReset = PEAK_RESET_COUNT;
} }
if (shiftBuffer.size() != desired_input_size) { if (shiftBuffer.size() != desired_input_size) {
@ -326,10 +364,9 @@ void SpectrumVisualProcessor::process() {
lastBandwidth = resampleBw; lastBandwidth = resampleBw;
lastInputBandwidth = iqData->sampleRate; lastInputBandwidth = iqData->sampleRate;
newResampler = true; newResampler = true;
peakReset.store(PEAK_RESET_COUNT); peakReset = PEAK_RESET_COUNT;
} }
unsigned int out_size = ceil((double) (desired_input_size) * resamplerRatio) + 512; unsigned int out_size = ceil((double) (desired_input_size) * resamplerRatio) + 512;
if (resampleBuffer.size() != out_size) { if (resampleBuffer.size() != out_size) {
@ -348,7 +385,7 @@ void SpectrumVisualProcessor::process() {
memcpy(fftInData, resampleBuffer.data(), fftSizeInternal * sizeof(liquid_float_complex)); memcpy(fftInData, resampleBuffer.data(), fftSizeInternal * sizeof(liquid_float_complex));
} }
} else { } else {
this->desiredInputSize.store(fftSizeInternal); this->desiredInputSize = fftSizeInternal;
num_written = data->size(); num_written = data->size();
if (data->size() < fftSizeInternal) { if (data->size() < fftSizeInternal) {
@ -492,7 +529,7 @@ void SpectrumVisualProcessor::process() {
} }
} }
float sf = scaleFactor.load(); float sf = scaleFactor;
double visualRatio = (double(bandwidth) / double(resampleBw)); double visualRatio = (double(bandwidth) / double(resampleBw));
double visualStart = (double(fftSizeInternal) / 2.0) - (double(fftSizeInternal) * (visualRatio / 2.0)); double visualStart = (double(fftSizeInternal) / 2.0) - (double(fftSizeInternal) * (visualRatio / 2.0));
@ -538,7 +575,7 @@ void SpectrumVisualProcessor::process() {
} }
} }
if (hideDC.load()) { // DC-spike removal if (hideDC) { // DC-spike removal
long long freqMin = centerFreq-(bandwidth/2); long long freqMin = centerFreq-(bandwidth/2);
long long freqMax = centerFreq+(bandwidth/2); long long freqMax = centerFreq+(bandwidth/2);
long long zeroPt = (iqData->frequency-freqMin); long long zeroPt = (iqData->frequency-freqMin);
@ -596,16 +633,19 @@ void SpectrumVisualProcessor::process() {
} }
} }
lastView = is_view.load(); lastView = is_view;
} }
void SpectrumVisualProcessor::setScaleFactor(float sf) { void SpectrumVisualProcessor::setScaleFactor(float sf) {
scaleFactor.store(sf); std::lock_guard < std::mutex > busy_lock(busy_run);
scaleFactor = sf;
} }
float SpectrumVisualProcessor::getScaleFactor() { float SpectrumVisualProcessor::getScaleFactor() {
return scaleFactor.load(); std::lock_guard < std::mutex > busy_lock(busy_run);
return scaleFactor;
} }

View File

@ -61,13 +61,19 @@ protected:
virtual void process(); virtual void process();
ReBuffer<SpectrumVisualData> outputBuffers; ReBuffer<SpectrumVisualData> outputBuffers;
std::atomic_bool is_view;
std::atomic_uint fftSize, newFFTSize;
std::atomic_uint fftSizeInternal;
std::atomic_llong centerFreq;
std::atomic_long bandwidth;
private: private:
//protects all access to fields below
std::mutex busy_run;
bool is_view;
size_t fftSize, newFFTSize;
size_t fftSizeInternal;
long long centerFreq;
size_t bandwidth;
long lastInputBandwidth; long lastInputBandwidth;
long lastBandwidth; long lastBandwidth;
bool lastView; bool lastView;
@ -80,7 +86,7 @@ private:
double fft_ceil_ma, fft_ceil_maa; double fft_ceil_ma, fft_ceil_maa;
double fft_floor_ma, fft_floor_maa; double fft_floor_ma, fft_floor_maa;
double fft_ceil_peak, fft_floor_peak; double fft_ceil_peak, fft_floor_peak;
std::atomic<float> fft_average_rate; float fft_average_rate;
std::vector<double> fft_result; std::vector<double> fft_result;
std::vector<double> fft_result_ma; std::vector<double> fft_result_ma;
@ -95,11 +101,11 @@ private:
std::vector<liquid_float_complex> shiftBuffer; std::vector<liquid_float_complex> shiftBuffer;
std::vector<liquid_float_complex> resampleBuffer; std::vector<liquid_float_complex> resampleBuffer;
std::atomic_int desiredInputSize; size_t desiredInputSize;
std::mutex busy_run;
std::atomic_bool hideDC, peakHold; bool hideDC, peakHold;
std::atomic_int peakReset; int peakReset;
std::atomic<float> scaleFactor; float scaleFactor;
std::atomic_bool fftSizeChanged; bool fftSizeChanged;
}; };

View File

@ -101,8 +101,7 @@ public:
if (input && !input->empty()) { if (input && !input->empty()) {
process(); process();
} }
} }
protected: protected: