Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

MAX/MIN with one argument NaN

Arjen_Markus
Honored Contributor I
3,213 Views

We ran into a peculiar behaviour of the MAX and MIN functions. The following program produces NaNs or actual numbers depending on the order of the arguments:

program maxnan
    use ieee_arithmetic

    implicit none

    real :: x, y

    x = 1.0
    y = ieee_value( y, ieee_quiet_nan )

    write(*,*) '1: ', max( x, y ), min( x, y )
    write(*,*) '2: ', max( y, x ), min( y, x )
end program maxnan

The output is:

 1:             NaN            NaN
 2:    1.000000       1.000000

Compiler version:

Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.9.0 Build 20230302_000000

 

Ifx gives the same result. If I build this program with gfortran I get:

 1:    1.00000000       1.00000000
 2:    1.00000000       1.00000000

The result with gfortran is more consistent, if only because you expect the result not to depend on the order of the arguments. I am not sure whether the result should be 1.0 or NaN, but the order definitely should not matter.

 

1 Solution
Steve_Lionel
Honored Contributor III
3,129 Views

An ICE is, of course, unacceptable.

For the intrinsic MAX, the standard does not say what happens when a value is a NaN, as the standard's model for real values does not include that concept. Therefore, the result could be considered processor-dependent.

In F2018's intrinsic module IEEE_ARITHMETIC there are IEEE_MAX_NUM and IEEE_MIN_NUM functions, where the descriptions say what happens here: "if exactly one of X and Y is a quiet NaN the result has the value of the other argument". Replacing MAX and MIN in this example with IEEE_MAX_NUM and IEEE_MIN_NUM, unfortunately, does not change the behavior, which is a bug.

F2023, which adopts a later edition of IEEE 60559, adds IEEE_MAX and IEEE_MIN which are subtly different. For those, "if either operand is a NaN, the result is a quiet Nan".

I will note that compiling with /fp:strict (-fp_model strict) is likely required here.

View solution in original post

0 Kudos
18 Replies
jdelia
New Contributor I
3,192 Views

Dear Arjen_Markus

In addition to the lack of consistency, using a test, with ifort and gfortran I get a similar result, but also with ifx I get an ICE:

$ cat /proc/version
Linux version 6.3.6-100.fc37.x86_64 (mockbuild@bkernel02.iad2.fedoraproject.org) (gcc (GCC) 12.3.1 20230508 (Red Hat 12.3.1-1), GNU ld version 2.38-27.fc37) #1 SMP PREEMPT_DYNAMIC Mon Jun  5 15:44:30 UTC 2023
$ ifort --version
ifort (IFORT) 2021.9.0 20230302
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.
$ ifort -warn all -O2 -o test203-ifort.exe -L${MKLROOT}/lib/intel64 -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -ldl test203.f90
$ test203-ifort.exe
 1:             NaN            NaN
 2:    1.000000       1.000000    
$ ifx --version
ifx (IFX) 2023.1.0 20230320
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.
$ ifx -warn all -O2 -o test203-ifx.exe -L${MKLROOT}/lib/intel64 -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -ldl test203.f90
          #0 0x0000000001f63112
          #1 0x0000000001fc5727
          #2 0x0000000001fc5850
          #3 0x00001459d77e9b20
          #4 0x0000000003d2a992
          #5 0x0000000003d2a8ac
          #6 0x0000000002e8e13d
          #7 0x00000000022ebeec
          #8 0x0000000002e84fbd
          #9 0x00000000022f30b7
         #10 0x0000000002e8519d
         #11 0x00000000022eaa8a
         #12 0x0000000001f08104
         #13 0x0000000001f06b83
         #14 0x0000000001eb5859
         #15 0x00000000020797c5
         #16 0x00001459d77d4510
         #17 0x00001459d77d45c9 __libc_start_main + 137
         #18 0x0000000001cf1729
test203.f90: error #5633: **Internal compiler error: segmentation violation signal raised** Please report this error along with the circumstances in which it occurred in a Software Problem Report.  Note: File and line given may not be explicit cause of this error.
compilation aborted for test203.f90 (code 3)
$ gfortran --version
GNU Fortran (GCC) 13.0.1 20230124 (experimental)
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gfortran --version
GNU Fortran (GCC) 13.0.1 20230124 (experimental)
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gfortran -march=native -mtune=native -fall-intrinsics -fcheck=all -fimplicit-none -fmax-errors=4 -std=f2018 -Wall -Waliasing -Warray-temporaries -Wcharacter-truncation -Werror -Wextra -Wimplicit-interface -Wimplicit-procedure -Wintrinsic-shadow -Wline-truncation -Wrealloc-lhs-all -Wsurprising -Wtabs -Wunused-parameter -O2 -o test203.exe test203.f90  
$ test203.exe 
 1:               NaN              NaN
 2:               NaN              NaN
0 Kudos
jimdempseyatthecove
Honored Contributor III
3,185 Views

IMHO the comparison of a NaN to a non-NaN, as with MIN and MAX (and related functions) should return NaN as the comparison is meaningless. Consider, had the QNaN been a SNaN, you would have expected the function to trigger a fault.

I agree the results should be consistent, however, I suspect the Fortran Standards committee may state that this is undefined behavior. Inserting a NaN test would adversely affect the performance of the function.

Jim Dempsey

0 Kudos
Arjen_Markus
Honored Contributor I
3,174 Views

I would have expected NaN as the answer as well, but the function MAXVAL returns an ordinary value in my very limited experiments, if the array contains a NaN. In this respect both compilers are unanimous. (I have a more extensive version of this program)

0 Kudos
JohnNichols
Valued Contributor III
3,170 Views

Let us constrain ourselves to the set of Integers,  then max and min are a valid operation on this set.  You now test NaN, it is not a member of the set and therefore the test should throw you an error marker, the only valid error marker is NaN, telling you one of the numbers is not in the test set.  

gfortran is in error, it will let you pass, but in reality what if you are testing 1/0.  ifort is in error.  This is actually quite critical and it should be defined in the standard for max and min. 

Better to throw an error than a satellite into the side of Mars because we made a simple mistake.  I can fix known errors, but I cannot fix that which I do not know.  

Caveat emptor. 

0 Kudos
jdelia
New Contributor I
3,156 Views

> gfortran is in error, it will let you pass,

Well, at least with

$ gfortran --version
GNU Fortran (GCC) 13.0.1 20230124 (experimental)

its output is:

$ test203.exe 
 1:               NaN              NaN
 2:               NaN              NaN

what it would be consistent and expected?

0 Kudos
JohnNichols
Valued Contributor III
3,140 Views

I am a bit lost, it appears in the first post that gfortran returns all 1's and in the last post it returns NaN. 

One of them has to be correct,  I do not use gfortran, I would never use gfortran and I will pass to my grave with the name gfortran never passing my lips. 

So I cannot resolve the difference.  But either the first post is correct or the last post, usually the last post is the end, except to shovel the dirt.   

Just not sure which one. 

0 Kudos
Steve_Lionel
Honored Contributor III
3,130 Views

An ICE is, of course, unacceptable.

For the intrinsic MAX, the standard does not say what happens when a value is a NaN, as the standard's model for real values does not include that concept. Therefore, the result could be considered processor-dependent.

In F2018's intrinsic module IEEE_ARITHMETIC there are IEEE_MAX_NUM and IEEE_MIN_NUM functions, where the descriptions say what happens here: "if exactly one of X and Y is a quiet NaN the result has the value of the other argument". Replacing MAX and MIN in this example with IEEE_MAX_NUM and IEEE_MIN_NUM, unfortunately, does not change the behavior, which is a bug.

F2023, which adopts a later edition of IEEE 60559, adds IEEE_MAX and IEEE_MIN which are subtly different. For those, "if either operand is a NaN, the result is a quiet Nan".

I will note that compiling with /fp:strict (-fp_model strict) is likely required here.

0 Kudos
Ron_Green
Moderator
3,126 Views

@Arjen_Markus  strange, I cannot get the ICE with IFX like you see.  What OS distro and version are you using?  And MKL is from the 2023.1.0 release?

 

cat /etc/redhat-release 
Fedora release 36 (Thirty Six)
rwgreen@orcsle153:~/quad/fnew$ 
rwgreen@orcsle153:~/quad/fnew$ echo $MKLROOT
/nfs/pdx/disks/cts2/tools/oneapi/2023.1.0/mkl/2023.1.0

orcsle153:~/quad/fnew$ 
orcsle153:~/quad/fnew$ ifx -warn all -O2 -o test203-ifx.exe -L${MKLROOT}/lib/intel64 -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -ldl test203.f90  -V -what

Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2023.1.0 Build 20230320
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

 Intel(R) Fortran 23.0-1474.2
GNU ld version 2.37-37.fc36
orcsle153:~/quad/fnew$ 
orcsle153:~/quad/fnew$ 

MAX and MIN are in the Intel Fortran Runtime Library which is shared with IFX and IFORT. Only 1 FRTL.  So really no need to test both ifort and ifx, you will get the same result.

 

0 Kudos
jdelia
New Contributor I
3,125 Views

Dear Ron_Green. Then, why there is an ICE with ifx and not with ifort, as it was shown, i.e.

$ ifort -warn all -O2 -o test203-ifort.exe -L${MKLROOT}/lib/intel64 -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -ldl test203.f90
$ test203-ifort.exe
 1:             NaN            NaN
 2:    1.000000       1.000000    
$ ifx --version
ifx (IFX) 2023.1.0 20230320
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.
$ ifx -warn all -O2 -o test203-ifx.exe -L${MKLROOT}/lib/intel64 -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -ldl test203.f90
          #0 0x0000000001f63112
          #1 0x0000000001fc5727
          #2 0x0000000001fc5850
          #3 0x00001459d77e9b20
          #4 0x0000000003d2a992
          #5 0x0000000003d2a8ac
          #6 0x0000000002e8e13d
          #7 0x00000000022ebeec
          #8 0x0000000002e84fbd
          #9 0x00000000022f30b7
         #10 0x0000000002e8519d
         #11 0x00000000022eaa8a
         #12 0x0000000001f08104
         #13 0x0000000001f06b83
         #14 0x0000000001eb5859
         #15 0x00000000020797c5
         #16 0x00001459d77d4510
         #17 0x00001459d77d45c9 __libc_start_main + 137
         #18 0x0000000001cf1729
test203.f90: error #5633: **Internal compiler error: segmentation violation signal raised** Please report this error along with the circumstances in which it occurred in a Software Problem Report.  Note: File and line given may not be explicit cause of this error.
compilation aborted for test203.f90 (code 3)

 

 

0 Kudos
jdelia
New Contributor I
3,111 Views

Dear Ron_Green.  Forget my last question: it turned out that there was a small spurious module in the source file. Sorry for the noise.

0 Kudos
Ron_Green
Moderator
3,110 Views

Still, a compiler should not crash, no matter what sources you give it.  I could look into it and get a fix.  And I can test with the upcoming Update 2 compiler and our nightly main branch.  If you can send it, that is.  If it's proprietary then perhaps send to me in a private message or open an issue on the Online Service Center.  
We are trying to stabilize IFX for the 2024.0 release.  Any help with this would be appreciated.

0 Kudos
jdelia
New Contributor I
3,102 Views

No, it was a simple old test on vectorization (taken from the internet) that shouldn't be in these tests at all. Anyway here it is:

 

module m_mod 
  implicit none 
  real, allocatable, dimension (:) :: aa, bb, cc
  !dir$ attributes align:32 :: aa, bb, cc
  !dir$ assume_aligned aa:32, bb:32, cc:32
end module m_mod

 

and the corresponding tests:

 

$ cat /proc/version
Linux version 6.3.6-100.fc37.x86_64 (mockbuild@bkernel02.iad2.fedoraproject.org) (gcc (GCC) 12.3.1 20230508 (Red Hat 12.3.1-1), GNU ld version 2.38-27.fc37) #1 SMP PREEMPT_DYNAMIC Mon Jun  5 15:44:30 UTC 2023

$ ifort --version
ifort (IFORT) 2021.9.0 20230302
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.

$ ifort -warn all -O0 -fp-model strict -c  test203a.f90
$ ifx --version
ifx (IFX) 2023.1.0 20230320
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

$ ifx -warn all -O0 -fp-model strict -c  test203a.f90
          #0 0x0000000001f63112
          #1 0x0000000001fc5727
          #2 0x0000000001fc5850
          #3 0x000014fc534a6b20
          #4 0x0000000002b65f96
          #5 0x0000000002f1d58d
          #6 0x0000000002e861cd
          #7 0x00000000022eaa8a
          #8 0x0000000001f08104
          #9 0x0000000001f06b83
         #10 0x0000000001eb5859
         #11 0x00000000020797c5
         #12 0x000014fc53491510
         #13 0x000014fc534915c9 __libc_start_main + 137
         #14 0x0000000001cf1729

test203a.f90: error #5633: **Internal compiler error: segmentation violation signal raised** Please report this error along with the circumstances in which it occurred in a Software Problem Report.  Note: File and line given may not be explicit cause of this error.
compilation aborted for test203a.f90 (code 3)

 

 

Ron_Green
Moderator
3,095 Views

This is a great help, actually.  These older Intel proprietary directives for alignment need to work with IFX.  This example gets an ICE with our main branch as well as with an early build for Update 2.  This needs to be fixed.  A lot of customers have these directives in their code so it's important that it works.   The idea is that what compiles with IFORT should compile with IFX.  Getting this bug fixed will help a lot of users, so thank you for sharing.  I'll get started on a fix that we can hopefully get into the 2024.0 compiler later this year.

0 Kudos
Ron_Green
Moderator
3,084 Views

Bug ID is CMPLRLLVM-48535


It is the directive

!dir$ assume_aligned aa:32, bb:32, cc:32

as you may have suspected. The compiler error was that a basic block was missing. This directive should be used with an executable block. when the executable block is missing, as in this case, I would like to see an error message instead of a crash. I would guess IFORT just ignored the problem. LLVM doesn't like bad IR and throws an exception (ICE).

If you use the dir$ assume_aligned on an executable block IFX is happy. And accepts and utilizes the directive in making vectorization and code gen decisions. For example, like this:

<code>

module m_mod 

 implicit none 

 real, allocatable, dimension (:) :: aa, bb, cc

 !dir$ attributes align:32 :: aa, bb, cc

contains

 subroutine initThem

 implicit none

 integer :: i

 allocate( aa(100), bb(100), cc(100))

 !dir$ assume_aligned aa:32, bb:32, cc:32

 do i=1,100

  aa(i) = 42.0

  bb(i) = 42.0

  cc(i) = 42.0

 end do

 end subroutine initThem

end module m_mod

</code>


Luckily, I don't think this will affect many users. I was concerned that this dir$ assume_aligned was not implemented. Fortunately it is, and works for standard usage. This missing basic block case tripped it up. We'll get that ICE fixed, hopefully with a useful error or warning message. Thanks for sending this to us!


0 Kudos
jdelia
New Contributor I
3,076 Views

Ahhh, ok. Thanks by the clarifications. Then, a fixed test for assume_aligned with ifx would be:

module m_mod 
  implicit none 
  real, allocatable, dimension (:) :: aa, bb, cc
!dir$ attributes align:32 :: aa, bb, cc
contains
  subroutine initthem ()
    implicit none
    integer :: i
    print *, "initthem begin"
    allocate (aa (100), bb (100), cc (100))
!dir$ assume_aligned aa:32, bb:32, cc:32
    do i=1, 100
      aa (i) = 2.0
      bb (i) = 4.0
      cc (i) = 6.0
    end do
    deallocate (aa, bb, cc)
    print *, "initthem end"
 end subroutine initthem
end module m_mod
program test
  use m_mod
  implicit none
  call initthem ()
end program test

and now the test is ok with ifx:

 

$ ifx -warn all -O2 -fp-model strict -o test203b-ifx.exe -L${MKLROOT}/lib/intel64 -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -ldl test203b.f90
$ test203b-ifx.exe 
 initthem begin
 initthem end

 

0 Kudos
Steve_Lionel
Honored Contributor III
3,061 Views

Ron, there is still an issue with IEEE_MAX_NUM and IEEE_MIN_NUM...

0 Kudos
Ron_Green
Moderator
3,053 Views

Sorry Steve, I missed your post earlier in this thread and got distracted by the shiny object that was the ICE. 

I modified the example to use the ieee_ min and max functions and see the bug you described.  I'll write it up.   Thanks for alerting me to this 2nd bug.

 

Bug ID is CMPLRLIBS-34527

Steve_Lionel
Honored Contributor III
2,983 Views

I could argue that the MAX/MIN behavior with /fp:strict should also be corrected.

0 Kudos
Reply