As the post on research articles but for blogs
Just read this blog in towardsdatascience that I think deserve a good applause: why you should consider using fortran as a data scientist
Shout out to the author, hope he is in community
As the post on research articles but for blogs
Just read this blog in towardsdatascience that I think deserve a good applause: why you should consider using fortran as a data scientist
Shout out to the author, hope he is in community
It’s good to have blog posts promoting Fortran. Here are some comments on the post.
The first code shown
program example
implicit none
integer :: i
i = 1
write(*,*) 'Hello world'
write(*,*) 1
end program example
has a bug because variable i
is set but never used. The author meant write(*,*) i
.
Here is a similar program that shows more Fortran features:
program example
implicit none
integer :: i, j
i = 2
j = 3
write(*,*) 'Hello world'
write(*,*) "i, j =", i, j
! ** is the power operator, and / between two integers truncates, as in Python 2 but not Python 3
write(*,*) "i+j, i-j, i**2, i/j =", i+j, i-j, i**2, i/j
end program example
! output: note that other compilers may give different spacing
! Hello world
! i, j = 2 3
! i+j, i-j, i**2, i/j = 5 -1 4 0
In the author’s knapsack code, one could use list comprehension (in Fortran terms, an implied do-loop) instead of writing
weight = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220]
A code that does this and prints the elapsed time is
program knapsack
implicit none
! define our variables
integer, parameter :: num_items = 22, max_weight = 800
integer :: i, j, k, m, new_weight, new_value, best_value
integer :: weight(num_items), value(num_items), new_combination(num_items), best_combination(num_items)
real :: t1, t2
call cpu_time(t1)
! initialize our item weights and values
weight = [(10*i, i=1, num_items)]
value = [10, 2, 3, 4, 20, 68, 75, 58, 9, 29, 56, 43, 38, 91, 27, 33, 200, 18, 300, 18, 400, 200]
best_value = 0
do i = 0, 2**num_items-1 ! iterate through all possible subsets of items
new_weight = 0
new_value = 0
! convert subset number to binary representation
k = i
do j = num_items, 1, -1
new_combination(j) = mod(k, 2) ! remainder is always 0 or 1, so we can make binary representation
k = k/2 ! divide by two to shift the bits in 'k' to the right
end do
! calculate total weight and value of items in subset
do j = 1, num_items
new_weight = new_weight + weight(j) * new_combination(j)
new_value = new_value + value(j) * new_combination(j)
end do
! check if subset is valid and update best value if necessary
if (new_weight <= max_weight .and. new_value > best_value) then
best_value = new_value
best_combination = new_combination
end if
end do
! print the items and their weight and value in the best solution
write(*,*) "Items in best combination:"
do j = 1, num_items
if (best_combination(j) == 1) then
write(*,*) "Item:", j, "Weight:", weight(j), "Value:", value(j)
end if
end do
write(*,*) "Best value: ", best_value
call cpu_time(t2)
print*,"elapsed time =", t2-t1
end program knapsack
The author finds that Fortran is 21 times faster than Python for his knapsack codes, but he compiles with gfortran -o brute brute_force.f90
. In Python, to speed up your code, you can try numba, or translate it to Cython, or PyPy, or other approaches, but you need to install another tool, and you may need to change your code. In Fortran it is easier – just use optimization options. Compiling the code above with various options
gfortran xknapsack.f90
gfortran -O3 xknapsack.f90
gfortran -O3 -march=native xknapsack.f90
gfortran -O3 -march=native -flto xknapsack.f90
gave times in seconds of
0.359375
0.125000
0.109375
0.093750
A further 4x speedup with no work is great. The author mentions
Newcomers may not know that since the 1990 standard, Fortran has operations on arrays and array slices, as in Matlab and NumPy.
ChatGPT should expand the user base of Fortran, since it can translate Python or other languages to it. Asking ChatGPT-4 to translate the author’s Python code gives, with one correction as shown,
program knapsack
implicit none
integer, parameter :: num_items = 22, max_weight = 800
integer :: best_value, new_weight, new_value, item
integer, dimension(num_items) :: weight, value, best_combination, new_combination
real(8) :: start_time, end_time, elapsed_time
integer :: i, j
logical :: in_knapsack
! Define weights and values
data weight /10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220/
data value /10, 2, 3, 4, 20, 68, 75, 58, 9, 29, 56, 43, 38, 91, 27, 33, 200, 18, 300, 18, 400, 200/
best_value = 0
best_combination = 0
call cpu_time(start_time)
! Brute force search
do i = 0, 2**num_items - 1
new_combination = transfer(i, new_combination)
new_combination = mod(new_combination, 2)
new_weight = dot_product(weight, new_combination)
new_value = dot_product(value, new_combination)
! original GPT line below
! if (new_weight <= max_weight) .and. (new_value > best_value) then
if (new_weight <= max_weight .and. new_value > best_value) then
best_value = new_value
best_combination = new_combination
end if
end do
call cpu_time(end_time)
! Output results
print *, "Items in best combination:"
do item = 1, num_items
in_knapsack = (best_combination(item) == 1)
if (in_knapsack) then
print '("Item ", i0, ": weight=", i0, ", value=", i0)', item, weight(item), value(item)
end if
end do
print *, "Best value: ", best_value
elapsed_time = end_time - start_time
print '("Time taken: ", f0.6, " seconds")', elapsed_time
end program knapsack
Unfortunately, it gives the wrong answer. I will look at it later today.
Another blog article about Fortran (already recently cited in the Anecdotal Fortran thread):
You will also find interesting articles about OOP in Fortran, and Fortran on Windows:
I don’t know if the author is here, else we should invite him to join the Discourse. => done
well, I was obliged to edit this message to add that last @amasaki203 article (2023-08-28) because of that Discourse message:
An error occurred: No more than 3 consecutive replies are allowed. Please edit your previous reply, or wait for someone to reply to you.
Updated 2023-09-23:
And a few blogs already cited in Anecdotal Fortran: