Fortran vs Python for number crunching

Fortran vs PythonSo it seems that Fortran is not so popular these days and there is a reason for that. Through the years, newer programming languages like Python have adapted to the overall evolution of computer science and had the chance of being developed in a time with more mature operating systems and hardware.

So today, Python is a well-designed language with a reasonably clean syntax, a comprehensive standard library, excellent included and third party documentation, widespread deployment, and the immediacy of a “scripting” style language (ie. no explicit compile step).

It is true that for some specific tasks, like the handling of strings, Fortran seems quite outdated comparing to Python. However for some certain tasks like lengthy numerical calculations there is a general belief that Fortran still has the lead. But to what extent is Fortran better for such tasks? How we may give a quantitative answer to such a question?

In a previous post for the purpose of comparing Fortran compilers, we have used a simple small algorithm (the Sieve of Eratosthenes) for finding prime numbers. Here the code is re-written in Python and it follows exactly the same logic as the code in Fortran, almost line-by-line. Check the two following blocks of code…

Fortran code

program primes
implicit none
integer, parameter :: max=10000000 ! Search for primes up to 10^7
integer :: i, j, k, product(max), imax, jmax, numprime

do k=1,100		  ! 100 iterations of the calculation
   do i = 1, max
      product(i) = 0
   enddo
   numprime=0

   imax = floor(sqrt(real(max)))
   do i = 2, imax
      if (product(i) == 0) then
         jmax = max/i
         do j = 2, jmax
            product(i*j) = 1
         enddo
      end if
   end do

   do i = 2, max
      if (product(i) == 0) then
         numprime = numprime + 1
      end if
   enddo

   print *, 'Number of primes  = ',numprime
enddo

end program primes

Python code

max=10000000

for k in range(1, 101):
    product = [0] * (max + 2)
    numprime=0
    imax = int(round(max**0.5))
    for i in range(2, imax+1):
        if product[i] == 0:
            jmax = int(max/i)
            for j in range(2, jmax+1):
                product[i*j]=1
    for i in range(2, max+1):
        if product[i] == 0:
            numprime=numprime+1
    print 'number of primes = ',numprime
    product[:] = []

Admittedly the python code is a bit more elegant than the corresponding fortran code (depending of course on how you perceive elegance…). But what about the speed of execution? Well it appears that on an early 2011 Macbook Pro (2.3GHz core i5, 4GB RAM 1333MHz DDR3) and Python version 2.7.5 it takes 800 seconds (something a bit less than 14min!!!) to repeat for a hundred times the search of prime numbers up to 10^7. Well that is freaking too much! The Fortran executable (compiled with gfortran v. 4.8.1) took 16.5 seconds in total for the same task. That means that for this particular example, Fortran is about 48 times faster than Python!!!┬áSurprisingly my trial to modify the python code and use a numpy matrix instead of a list, lead to even higher execution time. After the suggestion of a reader, I ran the same test with PyPy (version 2.2.1) instead of pure Pyhton. So with PyPy the calculation takes 50 seconds. Quite an improvement comparing to pure Python but still around 3 times slower than Fortran.

python_vs_pypy_vs_fortran_f

Someone might say that this is not a fair comparison since we have to do with an interpreted vs a compiled language. In any case this impressive difference reminds us that at least for parts of code that are slow and have extensive looping, interfacing python with Fortran has clear advantages! In the near future we will come back to the subject of interfacing Fortran and python code.

For the moment keep in mind that Fortran was developed back in an era where hardware was quite primitive and execution speed very important. In fact it was the first high-level language at all and its creators had to convince the community of Assembly programmers that Fortran can create machine code that is nearly as good as their hand crafted Assembly programs. This very important benefit is still inherited by Fortran today, and it really makes a difference.

4 thoughts on “Fortran vs Python for number crunching

    1. fortraner Post author

      I will give it a try… do you have an estimation how faster in general the executables would be comparing to PyPy?

      Reply
  1. Jake

    Hi, I came across your page and I had to comment on your code. You’d do well to make yourself more familiar with the features of Fortran, in this case, scalar assignments, masked assignments, and built-in functions. Take a look at the following:

    program primes
    implicit none
    integer, parameter :: max = 10000000
    integer :: i, j, k, imax, jmax, numprime
    logical :: prod(max) ! product is the name of a built-in function

    do k = 1, 100
    prod(:) = .TRUE. ! scalar assignment eliminates do loop
    numprime = 0
    imax = floor(sqrt(real(max)))

    do i = 2, imax
    if (prod(i)) then
    jmax = max/i
    prod(2*i:i*jmax:i) = .FALSE. ! masked assignment eliminates do loop
    end if
    end do

    print *, ‘Number of primes = ‘, count(prod)-1 ! built-in count function eliminates do loop
    end do

    end program primes

    Reply
    1. Jake

      Silly me, can improve this even more:

      program primes
      implicit none
      integer, parameter :: pmax = 10000000 ! max is a built-in function too
      integer :: i, k, imax
      logical :: prod(pmax) ! product is the name of a built-in function

      do k = 1, 100
      prod(:) = .TRUE. ! scalar assignment eliminates do loop
      imax = floor(sqrt(real(pmax)))

      do i = 2, imax
      if (prod(i)) then
      prod(2*i:pmax:i) = .FALSE. ! masked assignment eliminates do loop
      end if
      end do

      print *, ‘Number of primes = ‘, count(prod)-1 ! built-in count function eliminates do loop
      end do

      end program primes

      Reply

Join the discussion