Rewriting Fortran Software in Rust
mckeogh.tech
mckeogh.tech
This question is revisited a lot, but the general consensus has been that FORTRAN is fast, simple, easy to understand and code, and the compilers used are super optimized (Intel's FORTRAN compiler was really a gem - it managed to do a ton of automatic parallelization on modern hardware)
I'll see if I can find it, but I remember attending a conference talk at AGU in ~'08-10 called "Do-over or make-do" [1] that analyzed how many people-hours it would take to update all the climate modeling software (earth and space sciences are really huge on legacy FORTRAN code), and the conclusion of that talk was: use modern code/tools for glue, keep your climate models in FORTRAN.
There's a ton relating to precision - we had a huge ordeal converting our 32-bit space weather model to 64-bit because the change in precision changed our results, so we couldn't publish (in good conscious) without making sure the results weren't within a good margin of error. Anyhow.
This is always a fun thing to revisit now that I'm really far away from having to maintain any FORTRAN code any more :)
edit found it! [1]: https://www.easterbrook.ca/steve/2010/12/agu-session-on-soft... [2]: slides http://www.cs.toronto.edu/~sme/presentations/Easterbrook-AGU... Also randomly found this: http://www.moreisdifferent.com/2015/07/16/why-physicsts-stil...
That's not to say there isn't someone out there with this concern :)
For example.
More seriously, I could imagine a security flaw in numpy wreaking all sorts of havok. But it's also somewhat difficult for me to imagine that there are any security vulnerabilities left in BLAS. But then I remember Heartbleed.
Forgetting to initialize that last entry or initializing one too many entries by accident can cause random, very hard to track down, issues.
Security? Perhaps if your code is pulling chunks of data from a cloud source?
This is a really interesting dimension to the transition that I've never considered before. An actual change in correctness, not just compatibility. I would have thought for floats it would just add more decimal points
Our model was a space weather model of the solar wind speed and density - it was very iterative, and I think that iterative nature is what contributed to quirks in the transition - think of the issues when summing say, 0.1 ten times in Python (or other languages) - ultimately, we didn't need to do any real work to show that our converged model was within a margin of error and still presented the same results in terms of predicting solar flares - but it was still a lingering curiosity that the numbers weren't exactly the same (as you say!) - most of the work was done in finding the right compiler parameters to not break existing code, while taking advantage of the larger memory space.
I won't recommend Fortran unless the code has to be written by scientists who know nothing else. It has horrible string support, no data structure or algorithm library (like STL), no templates, few non-numeric libraries (e.g. http, json...) and (as above) buggy compilers. Furthermore, C++ gives you much more control over numerical speed when you need it.
That’s more than what C gives you out of the box ;)
Though, this is kind of ridiculous to even talk about, since the CPU and compiler itself are responsible for the greatest sins of hiding something unimaginably complex behind a simple interface.
Ah, the joys of the 6502 and the Commodore 64!
Our code was entirely FORTRAN 66 and 77, so that may explain why it worked so well for us.
(like the new jersey unemployment system in cobol)
:)
Though the beauty of fortran to me is really how easy it is to learn and make working code. That said - it's not elegant at all, probably a feature.
With gfortran I run into issues primarily when using the "newer" features of Fortran 2003/2018.
The reason is that for every hyper optimized climate model there are a thousand small or medium models. For these Julia offers sufficient performance and excellent developer experience.
When interfacing with C languages, that can be a big penalty (depending on the complexity of the algorithm).
It will probably take two generations of developers to make this happen, but well worth it. When I was studying atmospheric science I tried to understand OpenWRF (weather research forecasting) and the barrier was too high... And I had programming experience, imagine those with none!
An open source project is only as useful as it is accessible to it's average developer base.
That sounds like a question of numerical stability of the algorithm, rather than anything to do with the programming language, no?
Had you done some kind of external validation of the original results? If not, surely the new results are just as valid to publish as the original ones - any bugs are as much or more likely to be in the 32-bit than the 64-bit version.
Not that our model contributed much but we were one tiny part of the early warning system for solar flares for satellites and astronauts.
We admittedly weren’t super formal about the transition but wanted to make sure the differences wouldn’t be meaningful or propagate into other models we contributed to.
Also fwiw, we had no control or say over how others ran our model so they could have easily done their own 64 bit build of our code but I think it’s unlikely.
If that’s true, comparing system load or power usage could be a way to differentiate between the two implementations.
> As for my Rust experience, I’ve been using it for personal projects since ~2016 and I worked as a Rust software engineer at a startup in Berlin for a year after leaving high school.
Publish date on this blog post: July 14th, 2020
To me the biggest issue is that some simulations just need to run on 1000s or hundreds of 1000s of cores, and the primary technology that lets this happen is MPI (Message Passing Interface). I've been writing new Fortran code only because I want the simulation to be able to scale to this kind of size. The issue is that MPI only has official bindings for C and Fortran, so the only real choice I have is to keep programing in C or Fortran if I want to use MPI.
Any thoughts on this? Personally I would love to move towards more modern languages but without the proper libraries it is still a tough decision.
This Stack Overflow page comments more on this issue:
https://stackoverflow.com/questions/22949462/rust-on-grid-co...
Good points on the lack of certain features and ergonomic libraries. We're working hard on making this much better for Fortran [1] by developing a community-driven stdlib, package manager, and similar tools.
In fact, we'll have our monthly community call tomorrow [2] where we'll discuss the best way forward for a nice strings API in Fortran stdlib. I welcome everybody interested to join the call.
[1]: https://fortran-lang.org [2]: https://fortran-lang.discourse.group/t/fortran-monthly-call-...
I feel people forget to ask a more important question before they start a full rewrite and that is: Where is the hardware trends going and, is dedicated GPU, CUDA etc. even the future.
I feel it would be wasteful to spend a lot of time writing GPU specific code, Its not really maintainable on these scientific project (where only a select few people contribute, usually people that do the research).
Wow, even at similar optimization levels? -O3 for each?
gfortran: -O2 -ftree-vectorize -funroll-loops ifort: -O3
I don't have the timing results anymore. This was in 2018 on Xeon Platinum 8168.
I recently tried replacing -O2 with -Ofast -ffast-math to gfortran settings, which gives about 18% speed up. So still far from Intel. I recently proposed it here [1].
Coming up with these transformations is not the difficult part. That would be actually implementing these transformations correctly and keep the whole compiler optimization framework maintainable.
And of course there is certainly a cost for the improved runtime. Primarily in compile time and code size. For the Intel compiler it generally makes sense to sacrifice these in favor of runtime performance, because it is used on these kind of scientific codes a lot, but for gfortran the balance might different.
I have written several versions of a scientific simulation program in python, first using MPI (single machine) and then native multiprocessing. Using numpy and Pandas for all the heavy data operations. I really valued the ergonomics of python and native multiprocessing and found the MPI code to be not very human friendly. However, I ran into some very strange bugs relating to MKL and multiprocessing that just hung the program on large input sizes with MKL_NUM_THREADS above 1. I also had to bounce the input data to the worker processes to files due to mp not being able to pickle data when it got too large.
As soon as Apache arrow support in rust gets more feature complete I'll probably try to redo it there.
One of the things I find interesting is how the Fortran version is faster both with small and huge inputs, while the Rust version is faster for input sizes in the middle.
That said, I enjoyed reading through and finding “Edit: I was wrong about X.” Learning experiences all around!
Also, might have been mentioned but is this a typo?
> I’m guessing that FORTRAN is faster on small inputs due to the threading overheads, but faster on large inputs
Anyways, thanks! Enjoyed the article!
While I appreciate the strive for safety, and the effort being put into the rewrite, I believe in that particular case it would be more beneficial to rewrite it in ATS with safe formally-proved C rewrites/known to be safe inlined C calls.
I think the author meant FORTRAN was slower on small inputs?