Hi Aaron - I can't say exactly what the issue is, but here are a few thoughts. (1) make sure to set the min_output_buffer to somewhat more than the matrix size -- twice as large should be sufficient, but you can always go bigger if you want. (2) use just 1 throttle. make it downstream from the multiply, and then backpressure will keep the blocks before the throttle from running amok. (3) without setting some indicator to the scheduler (e.g., output_multiple or the I/O rate), the "work" function isn't guaranteed to be provided with data in the amounts required for it to do processing. You can always copy / cache locally in your block, but if you've done (1) then you can just use scheduler settings to handle the rest & guarantee good data I/O amounts. Sorry I can't be more precise; hope this helps! - MLD
On Mon, Dec 11, 2017, at 05:47 PM, Aaron Swan wrote:
Hi,I appear to be running into a deadlock issue when I try to merge two flow-graph paths. I've created an FFT block to perform strided FFTs. The basic idea is to store samples in an internal buffer until I have a full matrix. Once a matrix is full, perform a strided FFT into a second internal buffer and write to output. I'm consuming all samples, but not always returning samples.This block works great in a flow-graph until I try to merge two paths where one path contains the FFT block. So my simplified flow graph looks like[Tags strobe] --> [Throttle] --> [Strided FFT] --> [Multiply] --> [Null sink],where there is a second connection from [Throttle] --> [Multiply].Some restrictions: I need to use tags, so not using vectors on input/output makes things easier. I'm dealing with matrix sizes on the order of 128x512. I need to avoid tagged stream blocks.Some things I've tried: Inserting copy blocks in various places. Setting the min buffer size on the advanced tab of all the blocks to be 10*(matrix size). Inserting delay blocks on the second path. Modifying the forecast function to return nOutputs, 0, and rounded up to an integer multiple of the matrix size.Inserting a Strided FFT block on the second path does seem to get things to move, but inserting a delay does not. I could create a block that uses the same buffering scheme as the FFT, but I'm uncertain if that is an actual solution.Any thoughts as to why this deadlocks? See code below.Thanks in advance,Aaronimport numpy as npfrom gnuradio import grclass fft_py_cc(gr.basic_block):"""Perform FFT/IFFT on a matrix of dim0 x dim1 where dim1 is contiguous."""def __init__(self, dim0, dim1, axis=0, forward=True):self.axis = axisself.dim0 = dim0self.dim1 = dim1self.forward = forwardself.buffer = np.zeros((dim0,dim1), dtype=np.complex64)self.bufferOut = np.zeros((dim0,dim1), dtype=np.complex64)self.iBuffer = 0self.iBufferOut = dim0*dim1 # Set to the last sample to indicate not validgr.basic_block.__init__(self,name="fft_py_cc",in_sig=[np.complex64],out_sig=[np.complex64])def forecast(self, noutput_items, ninput_items_required):nMatrix = self.dim0*self.dim1nRequired = np.floor( (noutput_items - 1)/nMatrix )*nMatrix + nMatrixfor i in range(len(ninput_items_required)):ninput_items_required[i] = int(nRequired)#ninput_items_required[i] = noutput_items#ninput_items_required[i] = 0def general_work(self, input_items, output_items):nIn = input_items[0].shape[0]nOut = output_items[0].shape[0]iIn = 0iOut = 0nBuf = self.dim0*self.dim1nBo = self.dim0*self.dim1iBuf = self.iBufferiBo = self.iBufferOutiteration = 0while True:# Copy input samples to input buffernBufferRemain = nBuf - iBufnInputRemain = nIn - iInnCopy = min(nBufferRemain, nInputRemain)if nCopy > 0:self.buffer.ravel()[iBuf:iBuf + nCopy] = input_items[0][iIn:iIn + nCopy]iIn += nCopyiBuf += nCopy# FFT if ready (input buffer is full and output buffer is available)if iBuf == nBuf and iBo == nBo:if self.forward:self.bufferOut[:] = np.fft.fft(self.buffer, axis=self.axis)else:self.bufferOut[:] = np.fft.ifft(self.buffer, axis=self.axis)iBuf = 0iBo = 0# Copy to outputnBufferOutRemain = nBo - iBonOutputRemain = nOut - iOutnCopy = min(nBufferOutRemain, nOutputRemain)if nCopy > 0:output_items[0][iOut:iOut + nCopy] = self.bufferOut.ravel()[iBo:iBo + nCopy]iOut += nCopyiBo += nCopy# Check if we are doneif iOut >= nOut or iIn >= nIn:breakiteration += 1if iteration == 10000000:print "Error: FFT may be stuck."# Update and report consumed and processed samplesself.iBuffer = iBufself.iBufferOut = iBoself.consume(0, iIn)return iOut_______________________________________________Discuss-gnuradio mailing list
No comments:
Post a Comment