On Wed, 2017-12-27 at 16:18 -0500, Andy Walls wrote: > Hi Eugene > > > From: Eugene Grayver > > Date: Thu, 9 Nov 2017 19:52:35 +0000 > > > > There is a major problem with the way tags are propagated in blocks > > with non-integer relative rate. If the ratio is not a power of two, > > the numerical accuracy of the floating point will cause the output > > tags to diverge from the input tags. Consider the fractional > > resampler. It accumulates the timing offset in the range of 0 to 1. > > However tag propagation multiplies the ratio by the sample number. > > As > > the sample number grows the LSB accuracy of the ratio gets scaled > > by > > the ever larger value. For a ratio of 1.001 we saw divergence of > > 1000s of samples over a few minutes at 10msps.
OK, I've got a working fix for this: https://github.com/gnuradio/gnuradio/pull/1543 or https://github.com/awalls-cx18/gnuradio.git branch tag_fix4 You will need to install the mpir and mpir-devel packages for your distro, as this change adds a dependency on the MPIR library (libmpirxx.so and libmpir.so). With the attached GRC flowgraph, the fixed code shows no slips after 8 hours of continuous running on a modest laptop. Compare that with the baseline of gnuradio master, where after 8 hours, the tags have slipped 5 output samples to the right. You were right about it being a floating point precision problem, but the problem with the fractional resampler over short runs was (moslty) not in the gnuradio runtime, but the fractional resampler block itself: 1. The gnuradio-runtime propagated tags with double arithmetic; the fractional resampler block used mixed float & double arithmetic to propagate tags. 2. Floating point reciprocals aren't exact in the lsb's, so specifying set_relative_rate(1.0/resamp_ratio) was also introducing errors. I.e.: [ andy@pinto sw]$ ./rational3 1.001 Resample ratio: 1.0009999999999999 Resample ratio: 2254051613498933/2251799813685248 Numerator: 2254051613498933 Denominator: 2251799813685248 Relative rate: 0.99900099900099915 Relative rate: 4499100526843653/4503599627370496 Numerator: 4499100526843653 Denominator: 4503599627370496 Notice how the relative rate's numerator and denominator are not the same as the resample ratio's denominator and numerator. Geof: Could you please take a look at the newly added cmake module FindMPIR.cmake to see if it need changes for the Windows build? Jeff and Marcus: I'll address possible solutions for your observations (non-fixed relative rate and fraction tag offsets) in a separate post. I have a concept on how to address both, I think, but they can't be on master branch due to API changes. Regards, Andy
tag_prop_test.grc
Description: XML document
#include <stdlib.h> #include <iostream> #include <cmath> #include <boost/math/common_factor_rt.hpp> #include <mpirxx.h> #include <limits> int main(int argc, char *argv[]) { double resamp_ratio = strtod(argv[1], NULL); double relative_rate = 1/resamp_ratio; std::cout.precision(std::numeric_limits<double>::max_digits10); //--------------------------------------------------------------------- // Using MPIR's C++ interface static const mpq_class one_half(1,2); mpq_class resamp_ratio_q(resamp_ratio); mpq_class relative_rate_q(relative_rate); //ratio.canonicalize(); std::cout << "Resample ratio: " << resamp_ratio << std::endl; std::cout << "Resample ratio: " << resamp_ratio_q << std::endl; std::cout << "Numerator: " << resamp_ratio_q.get_num().get_ui() << std::endl; std::cout << "Denominator: " << resamp_ratio_q.get_den().get_ui() << std::endl; std::cout << std::endl; std::cout << "Relative rate: " << relative_rate << std::endl; std::cout << "Relative rate: " << relative_rate_q << std::endl; std::cout << "Numerator: " << relative_rate_q.get_num().get_ui() << std::endl; std::cout << "Denominator: " << relative_rate_q.get_den().get_ui() << std::endl; std::cout << std::endl; #if 0 //mpz_class offset(0x0800000000000003); uint64_t offset = 0x0800000000000003; mpq_class scaled = offset*ratio; mpz_class rscaled(scaled + one_half); mpz_class rscaled2; rscaled2 = offset * ratio + one_half; rscaled2 = offset * ratio + one_half + 2; std::cout << "Offset: " << offset << std::endl; std::cout << "Scaled offset: " << scaled << std::endl; std::cout << "Rounded scaled offset: " << rscaled << std::endl; std::cout << "Rounded scaled offset2: " << rscaled2 << std::endl; uint64_t rscaledint = rscaled.get_ui(); std::cout << "Native rounded scaled offset: " << rscaledint << std::endl; #endif exit(0); }
_______________________________________________ Discuss-gnuradio mailing list Discuss-gnuradio@gnu.org https://lists.gnu.org/mailman/listinfo/discuss-gnuradio