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

Cardino Code

JohnNichols
Valued Contributor III
823 Views

There is an interesting discussion on Cardino code evolving on the Fortran Discourse site.  FDs does not allow for zip files to be uploaded and I am loath to start a github point and waste days.  Plus most people are on both sites, and the important one is definitely.  

Here is the Intel Solution ( so far for Cardino).  

I also include the MNIST program from Milan C.  Interesting code, worth a look.  

 

0 Kudos
11 Replies
JohnNichols
Valued Contributor III
795 Views

As @mecej4 pointed out I had a mistake in Cardino.  

I had assumed incorrectly that the function ** in complex numbers would return the correct answer for the one third root, it appears not to and one needs the work around 

if((R%RE-SD%RE) .lt. 0.0D0) then
    T = -((abs(R-SD))**THIRDROOT)
    else
    T = (R - SD)**THIRDROOT
    end if

Where you check that the real part is negative - here the imaginary is zero and then the solution is trivially the 0ne third root of the positive number and then change the sign.  

 

Please note I was just having some fun, there are a lot more checks to put in the code, I was just showing you could get it to work. 

 

0 Kudos
JohnNichols
Valued Contributor III
785 Views

In order for MNIST to work in Intel Fortran properly as intended, we need to add RANDOM_SEED to teh published code, otherwise you are just repeating the same numbers over and over. Intel Fortran Random_number appears to take a constant from the computer if you do not use random_seed.

 

The manual tells us: the processor sets the seed for RANDOM_NUMBER to a processor-dependent value

Any ideas what this processor dependent CONSTANT is? 

Thanks 

0 Kudos
Steve_Lionel
Honored Contributor III
779 Views

What you really want to call is RANDOM_INIT (.FALSE.,.FALSE.) This is the standard way of initializing RANDOM_NUMBER to have nonrepeatable sequences. (The second argument controls the behavior of RANDOM_NUMBER across coarray images.)

What the specific constant value is isn't particularly important.

0 Kudos
JohnNichols
Valued Contributor III
749 Views

I used RANDOM SEED and that has stopped the endless repition of the same numbers.  I will change to your method.  

it is not important, merely asking why is a good scientific method.  

Screenshot 2022-05-24 092728.png

 

 

        !if (this_image() == 1) &
        print '(a,i2,a,f5.2,a,/)', '               Epoch ', n, ' completed.  Accuracy of the analysis is : ', accuracy(net, validation_images, label_digits(validation_labels),2) * 100, ' %'

    end do epochs


    print '(//"               End of the analysis. "//)'
    print '(80("-"))'

    contains

    real function accuracy(net, x, y, PR)
    type(network), intent(in out) :: net
    real, intent(in) :: x(:,:), y(:,:)
    INTEGER, INTENT(IN) :: PR
    INTEGER, ALLOCATABLE :: k(:)
    INTEGER, ALLOCATABLE :: m(:)
    REAL, ALLOCATABLE :: P(:)
    REAL, ALLOCATABLE :: Q(:)
    integer :: i, good, n
    good = 0
    n = size(x, dim=2)
    do i = 1, n
        k = maxloc(y(:,i))
        p = y(k,i)
        m = maxloc(net % output(x(:,i)))
        Q = x(m,i)
        if (all(maxloc(net % output(x(:,i))) == maxloc(y(:,i)))) then
            good = good + 1

        else
            if(PR .eq. 2) then
            if(i .lt. 9900) then 
                write(*,*)i,k-1
            end if
            end if
        end if

    end do
    accuracy = real(good) / size(x, dim=2)
    end function accuracy

    end program Zeus

 

 

The code works ok without the print statement, but the line 34 causes this crash - I am lost?

 

line 90 is in the program unit in Zeus, previously attached.  The function loops through 10000 numbers in two arrays to count same numbers.  

 

0 Kudos
Steve_Lionel
Honored Contributor III
744 Views

You call the function from a PRINT statement, and then have a PRINT statement in the function. Fortran doesn't allow you to start an I/O operation on a unit when one is already in progress on that unit. If you wanted to add this as a debugging statement, perhaps change it to a WRITE to unit 0 (STDERR).

0 Kudos
JohnNichols
Valued Contributor III
715 Views

Thanks for the answer.  I was intrigued that original developer used some interesting techniques from Fortran that are legal, but take a while to wrap your head around. 

 

0 Kudos
JohnNichols
Valued Contributor III
714 Views

 

T = (R - SD)**THIRDROOT

 

If T, R and SD are complex, and the real components of R and SD are not zero, but the complex are zero, and R-SD < 0 on the number line, then the answer to this problem is purely real,  so if R-SD = -125 than the answer is -5, but Intel Fortran does not give this answer, it gives a complex number, with a non zero imaginary part..  This comes from the Cardino problem.    

 

0 Kudos
JohnNichols
Valued Contributor III
689 Views

@Steve_Lionel , the problem of solving cubic equations was brought up on the Fortran discourse page. It is interesting to play with the code as I work on real stuff.  

The support in Intel Fortran for complex functions, on the face of it appears a bit terse.  So for example the sign function is not defined as a function  in Intel for complex.  The interesting challenge is the variations in the definitions, although it would appear to have four defined pairs if you look at the logic of the problem.  Wikipedia and Wolfram offer opinions.  

Am I missing something?  

 

0 Kudos
mecej4
Honored Contributor III
667 Views

There is a signum function defined for complex variables in mathematics.

It is defined as z/|z| for z not equal to 0, and as 0 for z = 0, z being a complex number.

What do you expect the signum of i to be? The signum of -i ?

I wish you would spell Cardano's name the usual way.

 

0 Kudos
Arjen_Markus
Honored Contributor I
650 Views

The way you would express the cubic root of a number x in Fortran or most other programming languages is by x**(1.0/3.0) (or pow(x, 1.0/3.0) or...). Note that the power is NOT 1/3, as it would be in mathematics, but a close approximation. And that is one of the problems: while with y = -5, y**3 gives -125, with x = 125 (positive, to avoid other problems), you cannot exactly get 5 via x**(1.0/3.0) - or if due to rounding it does happen to come out as 5 exactly, other values would lead to slight deviations from the mathematically correct value.

The solution for a programming language is not to allow negative values for a power of fractional value. An alternative might be to define a power of 1/n as we have a power of n as well as of x (n integer, x real). But even that poses problems: (-1.0)**(1/4) is a complex number, whereas (-1.0)**(1/3) is -1.0. 

0 Kudos
Steve_Lionel
Honored Contributor III
687 Views

The Fortran standard does not define SIGN on complex. As you note, it is not well-defined.

0 Kudos
Reply