Skip to content

4.0 rc1: Not enough warnings on i386 in test_data_out_of_range #9694

Closed

Description

@olebole

When running on i386, I get the following failures due to missing warnings:

_______________ test_data_out_of_range[False-fast_reader2-True] ________________

parallel = False, fast_reader = {'parallel': False, 'use_fast_converter': True}
guess = True

    @pytest.mark.parametrize("guess", [True, False])
    # fast_reader configurations: False| 'use_fast_converter'=False|True
    @pytest.mark.parametrize('fast_reader', [False, dict(use_fast_converter=False),
                                             dict(use_fast_converter=True)])
    @pytest.mark.parametrize("parallel", [False, True])
    def test_data_out_of_range(parallel, fast_reader, guess):
        """
        Numbers with exponents beyond float64 range (|~4.94e-324 to 1.7977e+308|)
        shall be returned as 0 and +-inf respectively by the C parser, just like
        the Python parser.
        Test fast converter only to nominal accuracy.
        """
        # Python reader and strtod() are expected to return precise results
        rtol = 1.e-30
    
        # Update fast_reader dict; adapt relative precision for fast_converter
        if fast_reader:
            fast_reader['parallel'] = parallel
            if fast_reader.get('use_fast_converter'):
                rtol = 1.e-15
            elif np.iinfo(np.int_).dtype == np.dtype(np.int32):
                # On 32bit the standard C parser (strtod) returns strings for these
                pytest.xfail("C parser cannot handle float64 on 32bit systems")
    
        if parallel:
            if not fast_reader:
                pytest.skip("Multiprocessing only available in fast reader")
            elif TRAVIS:
                pytest.xfail("Multiprocessing can sometimes fail on Travis CI")
    
        fields = ['10.1E+199', '3.14e+313', '2048e+306', '0.6E-325', '-2.e345']
        values = np.array([1.01e200, np.inf, np.inf, 0.0, -np.inf])
        with catch_warnings(AstropyWarning) as w:
            t = ascii.read(StringIO(' '.join(fields)), format='no_header',
                           guess=guess, fast_reader=fast_reader)
        if fast_reader and not parallel:  # Assert precision warnings for cols 2-5
>           assert len(w) == 4
E           assert 3 == 4
E            +  where 3 = len([<warnings.WarningMessage object at 0xe8d488b0>, <warnings.WarningMessage object at 0xe8d48538>, <warnings.WarningMessage object at 0xe8d48c10>])

astropy/io/ascii/tests/test_c_reader.py:1067: AssertionError

The same happens for False-fast_reader2-False.

Activity

  1. dhomeier commented on Nov 27, 2019

    @dhomeier
    Contributor

    What system and compiler is this?
    When you run

    ascii.read(BytesIO('10.1E+199 3.14e+313 2048e+306 0.6E-325 -2.e345'.encode('ascii')), format='no_header', fast_reader={'parallel': False, 'use_fast_converter': True})
    

    could you check which column does not raise a warning and what is read in from that col?

  2. olebole commented on Nov 27, 2019

    @olebole
    MemberAuthor

    That is Debian unstable, gcc 9.2.1.

    >>> from astropy.io import ascii
    >>> from io import BytesIO
    >>> ascii.read(BytesIO('10.1E+199 3.14e+313 2048e+306 0.6E-325 -2.e345'.encode('ascii')), format='no_header', fast_reader={'parallel': False, 'use_fast_converter': True})
    WARNING: OverflowError converting to FloatType in column col2, possibly resulting in degraded precision. [astropy.io.ascii.fastbasic]
    WARNING: OverflowError converting to FloatType in column col4, possibly resulting in degraded precision. [astropy.io.ascii.fastbasic]
    WARNING: OverflowError converting to FloatType in column col5, possibly resulting in degraded precision. [astropy.io.ascii.fastbasic]
    <Table length=1>
       col1     col2    col3    col4    col5 
     float64  float64 float64 float64 float64
    --------- ------- ------- ------- -------
    1.01e+200     inf     inf     0.0    -inf
    
  3. added this to the v4.0 milestone on Nov 27, 2019
  4. pllim commented on Nov 27, 2019

    @pllim
    Member

    @taldcroft , any ideas?

  5. dhomeier commented on Nov 27, 2019

    @dhomeier
    Contributor

    Hmm, the stable gcc version is 9.2.0, and apparently there haven't been any gnu.org "subsubversion" releases since 4.9.4; I'm wondering what the official status of Debian's 9.2.1 is...

  6. dhomeier commented on Nov 27, 2019

    @dhomeier
    Contributor

    But then this apparently pops up in our hand-coded xstrtod, not the builtin one.
    AFAICS the difference to the other input numbers is that 2048e+306 will not already set
    errno = ERANGE on the exponent (which by itself is still in the safe range), but only right afterwards on comparison of the converted
    (number == HUGE_VAL || number == -HUGE_VAL)
    – as number obviously is inf, I am puzzled why that comparison is not true. Maybe it now counts as inf > HUGE_VAL...?

    Could you change tokenizer.c to
    if (number >= HUGE_VAL || number <= -HUGE_VAL)
    and check what happens?

  7. olebole commented on Nov 27, 2019

    @olebole
    MemberAuthor

    That seems to work now:

    Python 3.7.5 (default, Oct 27 2019, 15:43:29) 
    [GCC 9.2.1 20191022] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from astropy.io import ascii
    >>> from io import BytesIO
    >>> ascii.read(BytesIO('10.1E+199 3.14e+313 2048e+306 0.6E-325 -2.e345'.encode('ascii')), format='no_header', fast_reader={'parallel': False, 'use_fast_converter': True})
    WARNING: OverflowError converting to FloatType in column col2, possibly resulting in degraded precision. [astropy.io.ascii.fastbasic]
    WARNING: OverflowError converting to FloatType in column col3, possibly resulting in degraded precision. [astropy.io.ascii.fastbasic]
    WARNING: OverflowError converting to FloatType in column col4, possibly resulting in degraded precision. [astropy.io.ascii.fastbasic]
    WARNING: OverflowError converting to FloatType in column col5, possibly resulting in degraded precision. [astropy.io.ascii.fastbasic]
    <Table length=1>
       col1     col2    col3    col4    col5 
     float64  float64 float64 float64 float64
    --------- ------- ------- ------- -------
    1.01e+200     inf     inf     0.0    -inf
    
  8. pllim commented on Nov 27, 2019

    @pllim
    Member

    Does this mean there needs to be a patch for tokenizer.c? Thanks for looking into this, @dhomeier !

  9. dhomeier commented on Nov 27, 2019

    @dhomeier
    Contributor

    The above would be an easy enough fix. Just wondering if this is really conforming to standard, or a compiler bug after all. @olebole would you mind also testing
    if (number == INFINITY || number == -INFINITY) ?
    That appears to be the more up-to-date way to do it, although by all accounts the two seem to be supposed to work quite interchangeably.

  10. olebole commented on Nov 27, 2019

    @olebole
    MemberAuthor

    @dhomeier No -- INFINITY does not work. I could (wildly, without any competence) guess that double values in registers on i386 are 80bit (not 64); so they may be internally still finite but converted to infinity when put into storage cells (depending on compiler optimization). That would explain why this does not happen on other 32 bit platforms: arm and mips build nicely.

  11. olebole commented on Nov 27, 2019

    @olebole
    MemberAuthor

    The gcc-9 debian/changelog states for the origin:

    gcc-9 (9.2.1-1) unstable; urgency=medium
    
      * Update to SVN 20190813 (r274380) from the gcc-9-branch.
        - Fix PR fortran/91422, PR lto/91375, PR driver/91130, PR driver/91130,
          PR c++/91378, PR c++/90538, PR fortran/91424, PR fortran/91359,
          PR fortran/42546, PR fortran/91414, PR libstdc++/90361.
      * Minor updates to debian/copyright for GCC 9.
      * Include a snapshot of the gm2 tarball.
      * Add copyright information for gcc/gm2, gcc/testsuite/gm2 and libgm2.
    
  12. dhomeier commented on Nov 27, 2019

    @dhomeier
    Contributor

    @dhomeier No -- INFINITY does not work. I could (wildly, without any competence) guess that double values in registers on i386 are 80bit (not 64); so they may be internally still finite but converted to infinity when put into storage cells (depending on compiler optimization). That would explain why this does not happen on other 32 bit platforms: arm and mips build nicely.

    Well, for 32 bit platforms the fast_reader versions of the test are marked xfail anyway, but the 80 bit register length could come in here indeed. One further variant to test would be
    if (number == __builtin_inf() || number == -__builtin_inf())
    – maybe using the builtin functions instead could indeed let the whole comparison run in the register. But I am somewhat out of my depth here too, at least I could not identify anything obviously related in the tracker log.

  13. dhomeier commented on Nov 27, 2019

    @dhomeier
    Contributor

    Come to think, even if that comparison to __builtin_inf() works with the 80 bit-values, it would take something larger than 2.048e309 to trigger it. But that's not what we actually want to know anyway - I think we want a warning whenever loss of precision is encountered on storing that value as a np.float64. So number >= HUGE_VAL is probably the way to go - at least unless and until we somehow manage to extract that number at the full 80 bit precision and store it as np.float128...

  14. pllim commented on Dec 3, 2019

    @pllim
    Member

    So, is there a clear path forward to resolve this for RC2?

  15. dhomeier commented on Dec 3, 2019

    @dhomeier
    Contributor

    Unless there are still concerns that @olebole's diagnosis might somehow be wrong and this a gcc 9.2.1 bug after all, I propose to go for changing the comparison to >= HUGE_VAL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions