7 comments

  • khuey 1 hour ago
    If you don't _need_ subnormals MXCSR.DAZ/FTZ (which you can get gcc to set via -mdaz-ftz) will let you ignore all of this.
    • bee_rider 34 minutes ago
      IIRC intel’s compilers enable FTZ/DAZ, at least at higher optimization levels.
      • account42 4 minutes ago
        GCC does with the infamous -ffast-math as well.
  • mzs 12 minutes ago
    Are the results compared across architectures?
    • noselasd 11 minutes ago
      The article covers 5 CPUs.
  • pixelpoet 35 minutes ago
    This has been the case since a zillion years, since the Core 2 Duo days at minimum.
    • account42 28 minutes ago
      The interesting part is that this seems to be Intel-specific.
      • pixelpoet 12 minutes ago
        That's what I mean though- in the Core 2 Duo vs K8 / Athlon days, Intel was much slower for denormals and subnormals than AMD. I'm not sure why but I thought this was common knowledge.
  • juancn 1 hour ago
    Apparently it only happens on P-cores, recent E-cores have a fast path for subnormals.
    • rustybolt 35 minutes ago
      That seems weird. They did throw extra hardware at it to speed it up for the efficient cores, but not for the performance cores?
  • gwbas1c 37 minutes ago
    I'm still trying to understand what a subnormal number is; IE, I'm looking for the TLDR so I know just enough to know if I'm using them and need to learn more.

    Unfortunately, the Wikipedia article, while probably being accurate, doesn't give a clear and concise answer.

    IE, is 0.0001 a subnormal? Or is it 0.000000000000000000001?

    • account42 9 minutes ago
      Floating point numbers are usually interpreted as

          sign * 1.mantissa * 2 ^ exponent
      
      where sign, mantissa and exponent are fixed bit width integers. The 1. before the number is normally implicit because it would be a waste of a bit to encode it when you could just use a diferent exponent to represent such a number.

      However with this simple scheme the number zero and a relatively large gap around it cannot be represented (relatively large to the gap between the smallest and next smalles number that can be represented).

      So there is a special case where for the smallest encodeable exponent the mantissa must also specify that 1. or 0. prefix. Because its a special case it needs special handling that clever silicon engineers might think is unimportant enough to handle in microcode instead of dedicated silicon.

      x86 has a mode to assume that all such small numbers are actually equal to zero which can then be handle without microcode fallback. Technically its even a bit more complicated because x86 has two different float implementations and for at least SSE floats you can control the denormals-are-zero and flush-(denormals)-to-zero-(when writing) modes independently. GCC -ffast-math actual enables that mode for the entire main thread.

      AFAIK ARM NEON always works in that mode so the Gravion and Apple benchmarks might be unfair here undless you compare with DAZ and FTZ enabled on Intel. No idea if the AMD benchmarks might have used different modes. Because the flags are global per thread you can easily have unrelated loaded libraries messing the benchmark up.

    • ant6n 20 minutes ago
      Usually IEEE floats have an implied 1 in the front. So for the standard represented numbers, there's some minimum number 1.bbbbbb.. * 2^-N. This allows 1bit more precision than is actually stored.

      between any two numbers, there's basically the same epsilon difference, but from the smallest number to zero it's bigger.

      A subnormal number breaks that convention, it just becomes 0.bbbbb... * 2^-N. As the numbers get smaller, the relative difference between the numbers gets larger. That also means their precision is smaller than the normal floats.

  • rf15 2 hours ago
    ...Is this running extra micro code to fix some hardware bug/unreliability? How can this happen? Doesn't look like a normal design decision.
    • Sharlin 1 hour ago
      Subnormal numbers have a different, basically fixed-point, representation. They exist in order to bridge the large (relatively speaking; indeed "infinite" in a sense) gap between the least positive normal number, zero, and the greatest negative normal number, caused by the usual significand-exponent representation.

      Most "mundane" uses of floating point have no need for subnormal numbers, and numbers that underflow could just be flushed to zero. But they’re sometimes important in scientific computing to ensure sufficient smoothness around zero, avoiding precision issues.

      • nayuki 7 minutes ago
        I can think of one useful property of subnormal numbers off the top of my head. If subnormal processing is enabled, then for all finite values of `a` and `b`, `a != b` if and only if `a - b != 0`. But if subnormals are flushed to zero, then two tiny normal distinct values `a` and `b` would have a subnormal difference that is flushed to zero.
      • bee_rider 10 minutes ago
        I don’t know how useful they are in scientific computing either, really. They are less precise than normalized numbers… if flushing them makes a difference I think it is a bad algorithm smell.
    • aardvark179 1 hour ago
      I don’t know if any bugs contribute to this but this in the intel case but it has been very common historically for subnormal performance to be lower on many processors, and things like the Alpha required you to handle them in software if the COU fired a trap.

      Have a look at https://en.wikipedia.org/wiki/Subnormal_number for some context.

    • duped 44 minutes ago
      It's to satisfy IEEE 754 and it's been this way for decades.
      • pohl 43 minutes ago
        Does that mean that the ARM processors in the writeup are not satisfying IEEE 754?
        • tasty_freeze 30 minutes ago
          It probably means Apple spent the silicon to handle subnormals at full speed in hardware, rather than triggering a slow microcode handler for such numbers.
      • david-gpu 6 minutes ago
        I don't know who is down voting you. AFAIK IEEE 754:2008 does require support for subnormals. You can optionally have modes that flush them to zero, but you must support subnormals.

        I haven't done any work on this stuff since 2019, so my memory may be hazy.