# 79 Languages speed competition: Can we make Fortran win?

**URL:** <https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038>\
**Category:** Uncategorized\
**Created:** [March 24, 2022, 7:40am UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038 "2022-03-24T07:40:01Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![CRquantum](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/crquantum/32/730_2.png) [@CRquantum](https://fortran-lang.discourse.group/u/CRquantum)\
**Post date:** [March 24, 2022, 7:40am UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/1 "2022-03-24T07:40:01Z")

</div>

Dear all,

There is language speed competition! I just find an interesting video on Youtube,

[![](https://global.discourse-cdn.com/free1/uploads/fortran_lang/original/2X/e/e0fc3f4533013e8a04276b076d5868f14a6396a0.jpeg "45 Computer Languages Compared: Which is FASTEST?") ](https://www.youtube.com/watch?v=pv4Yq35Chx0)

The guy called Dave Plummer seems legit.

The language speed challenge is simple,  
given 5 seconds, from 1 to 10^6, find as many as prime number per unit time as possible (correct me if I was wrong). Anyway, the higher the number the faster the language is.  
Initially perhaps there 45 Language in the completion, now it seems there are at least 79.

Correct me if I was wrong. But it seems Fortran’s performance isn’t great, among 79 languages, only at 21th position,

 ![image](https://global.discourse-cdn.com/free1/uploads/fortran_lang/original/2X/6/6da0ecf9c24091bae2e406490df196cb0ae91439.jpeg)

Two columns are the most important, passes, and passes/s/t (pass per second per thread). The number there the higher the better.

**I just have one simple question: Can we make Fortran the champion? Can we? Shall we?**

PS.  
All the information is in that his github,

> **[GitHub - PlummersSoftwareLLC/Primes: Prime Number Projects in C#/C++/Python](https://github.com/PlummersSoftwareLLC/Primes)**
>
> Prime Number Projects in C#/C++/Python. Contribute to PlummersSoftwareLLC/Primes development by creating an account on GitHub.

The result report can be found here,  
[https://plummerssoftwarellc.github.io/PrimeView/?rc=30&sc=rc&sd=True](https://plummerssoftwarellc.github.io/PrimeView/?rc=30&sc=rc&sd=True)  
One report for example is here,  
[https://plummerssoftwarellc.github.io/PrimeView/report?id=rbergen-1648101155.json&hi=False&hf=False&hp=True&fi=&fp=&fa=&ff=&fb=&tp=True&sc=pp&sd=True](https://plummerssoftwarellc.github.io/PrimeView/report?id=rbergen-1648101155.json&hi=False&hf=False&hp=True&fi=&fp=&fa=&ff=&fb=&tp=True&sc=pp&sd=True)

There are currently two Fortran solutions there,

> **[Primes/PrimeFortran at drag-race · PlummersSoftwareLLC/Primes](https://github.com/PlummersSoftwareLLC/Primes/tree/drag-race/PrimeFortran)**
>
> drag-race/PrimeFortran

I believe Fortran should perform better than it is now!

---

<div class="post-metadata">

**Author:** ![Pap](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pap/32/1305_2.png) [@Pap](https://fortran-lang.discourse.group/u/Pap)\
**Post date:** [March 24, 2022, 8:38am UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/2 "2022-03-24T08:38:55Z")

</div>

Assembly at position #24? Seriously? And… Lisp at #1? And there is more… Java, the worst language ever, at higher position that Fortran? I could go on, but I think enough is enough… Unless I am reading this table wrong, this is totally nonsense.

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [March 24, 2022, 11:43am UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/3 "2022-03-24T11:43:47Z")

</div>

Does not make much sense to me, either. Lisp/C++/D performing 4-5 orders of magnitude (!) faster than the others. But I gave a try the C++ and Fortran solutions and the numbers are similar to those in the table above. So either there is such a difference in the algorithms used or I do not understand what is happening.

---

<div class="post-metadata">

**Author:** ![gnikit](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/gnikit/32/1213_2.png) [@gnikit](https://fortran-lang.discourse.group/u/gnikit)\
**Post date:** [March 24, 2022, 1:42pm UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/4 "2022-03-24T13:42:25Z")

</div>

Having had a very quick look at the C++ (sol 3) and Fortran (sol1 & 2) the solutions are not quite equivalent. Although they implement the same base algorithm C++ has a lot more going on under the hood.

C++ uses unsigned ints, bitwise operators, and most importantly compile time optimisations like precomputed square roots (and it is thread, although the default number of threads is 1). All that in addition to using a fixed size buffer.

On the other hand the Fortran (`prime-8bit`) implementation uses dynamic storage at every iteration of the sieve and the normal `sqrt` intrinsic function. Also, I think the use of OOP in this case might be adding overhead and thus hindering performance.

We could probably boost our score if we used the preprocessor and removed some of the OOP.

PS My guess is that the majority of the time is spent in [`clear_bits`](https://github.com/PlummersSoftwareLLC/Primes/blob/e30cbfcec4f7ca97378323c0ace6c6b2b8d794fa/PrimeFortran/solution_2/prime-8bit.f08#L96-L107) followed by calls to allocate and [`get_bit`](https://github.com/PlummersSoftwareLLC/Primes/blob/e30cbfcec4f7ca97378323c0ace6c6b2b8d794fa/PrimeFortran/solution_2/prime-8bit.f08#L82-L94)

Here are the `gprof` results using `ifort -Ofast -pg` (gofrtran results were comparable)

 ![image](https://global.discourse-cdn.com/free1/uploads/fortran_lang/original/2X/6/6ff1e735635463f7ff9cfb1c7ba74fcf117da70f.png)

---

<div class="post-metadata">

**Author:** ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)\
**Post date:** [March 24, 2022, 6:57pm UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/5 "2022-03-24T18:57:21Z")

</div>

Finding primes is not a bad benchmark, but the fast algorithms seem to use bitfields. I wonder if one could use logical arrays and let the Fortran compiler implement it as a bitfield.

For Fortran it’s better to do some more numerical benchmark, like solving some equation.

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [March 24, 2022, 7:01pm UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/6 "2022-03-24T19:01:22Z")

</div>

I have modified the `type PrimeSieve` definition to contain  
`integer(kind=int8), dimension(500000) :: raw_bits` and commented out `deallocate` in the finalizer but it did not help.  
I have also tried to change int64 to int32, also no significant change.

@gnikit’s profiling effort give a hint regarding `clear_bits ` procedure being the major cpu-eater. I checked how many single bytes get zeroed in a benchmark run. The result is astonishing. My home machine executed 4577 passes in 5 seconds, calling `clear_bits` 768936 times and zeroing total of 3712226197 (3.7G) bytes. There seems to be plenty to improve but how? It seems that the `step` dummy is never 2, so the loop step is always different than 1. If it were 1, the compiler would arrange a call to `memset`.

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [March 24, 2022, 7:05pm UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/7 "2022-03-24T19:05:51Z")

</div>

> [@certik](#):
>
> I wonder if one could use logical arrays and let the Fortran compiler implement it as a bitfield.

Actually there is a version using logical array on GitHub but it performs even worse

---

<div class="post-metadata">

**Author:** ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)\
**Post date:** [March 24, 2022, 7:30pm UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/8 "2022-03-24T19:30:00Z")

</div>

I assume Fortran compilers don’t optimize it well, but they could.

Is the idea that bitfield requires 8x less memory than a byte array, and thus even though you have to do bit operations and more complicated indexing to use it, it still ends up faster because you don’t have to copy as much data from memory to registers?

---

<div class="post-metadata">

**Author:** ![gnikit](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/gnikit/32/1213_2.png) [@gnikit](https://fortran-lang.discourse.group/u/gnikit)\
**Post date:** [March 24, 2022, 7:32pm UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/9 "2022-03-24T19:32:35Z")

</div>

If I recall correctly, the existing implementation on GitHub uses normal logicals i.e. 32bit which would explain the performance difference. I suspect that if we were able to use 1bit arrays instead of 8bit we would get similar performance to C++.

Another potential bottleneck is the cache performance. The `raw_bits` array realistically does not fit in any of the CPU caches so accessing it with non consecutive indices would theoretically result in poorer performance. In the context of Eratosthenes’ sieve I don’t see a straightforward way to avoid that.

---

<div class="post-metadata">

**Author:** ![gnikit](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/gnikit/32/1213_2.png) [@gnikit](https://fortran-lang.discourse.group/u/gnikit)\
**Post date:** [March 24, 2022, 7:41pm UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/10 "2022-03-24T19:41:25Z")

</div>

That is my understanding. However from personal experience having used bitfields in Fortran for wavelet compression the performance gains were not impressive (the savings in memory obviously were, but that is a different matter).

---

<div class="post-metadata">

**Author:** ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)\
**Post date:** [March 24, 2022, 7:46pm UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/11 "2022-03-24T19:46:50Z")

</div>

I also couldn’t get bitfields to perform faster than byte (8bit) arrays (in C or Fortran).

Regarding fast prime generation, I think this might be one of the fastest codes out there:

- [GitHub - kimwalisch/primesieve: 🚀 Fast prime number generator](https://github.com/kimwalisch/primesieve) (see also the algorithm [description](https://github.com/kimwalisch/primesieve/wiki/Segmented-sieve-of-Eratosthenes))
- And a C implementation: [GitHub - TotallyNotChase/cFastSieve: 🚀 Fastest (probably) Sieve of Eratosthenes implementation, in C](https://github.com/TotallyNotChase/cFastSieve)

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [March 24, 2022, 9:37pm UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/12 "2022-03-24T21:37:49Z")

</div>

Calling repeatedly `primesieve_count_primes(0,1000000)` for 5 seconds gives 35 times less passes done than the C++ winner in the table (flo80-pol-constexpr), the latter requiring C++20 features.

---

<div class="post-metadata">

**Author:** ![Jweber](https://avatars.discourse-cdn.com/v4/letter/j/e95f7d/32.png) [@Jweber](https://fortran-lang.discourse.group/u/Jweber)\
**Post date:** [March 27, 2022, 11:39am UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/13 "2022-03-27T11:39:32Z")

</div>

I am actually the author of the code presented in the video. In the github repository there is actually another, object-oriented solution by another author I would have preferred to be chosen.

---

<div class="post-metadata">

**Author:** ![Jweber](https://avatars.discourse-cdn.com/v4/letter/j/e95f7d/32.png) [@Jweber](https://fortran-lang.discourse.group/u/Jweber)\
**Post date:** [March 27, 2022, 11:42am UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/14 "2022-03-27T11:42:17Z")

</div>

The reason for using a bitfield was to reproduce the algorithm presented in the first video of the comparison series as accurately as possible.

---

<div class="post-metadata">

**Author:** ![Jweber](https://avatars.discourse-cdn.com/v4/letter/j/e95f7d/32.png) [@Jweber](https://fortran-lang.discourse.group/u/Jweber)\
**Post date:** [March 27, 2022, 11:44am UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/15 "2022-03-27T11:44:36Z")

</div>

The reason why  
in these solutions the results were computed at compile time so there was not much to do at run time…

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [March 27, 2022, 12:22pm UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/16 "2022-03-27T12:22:36Z")

</div>

It turns out you can do this in Fortran too! See the [recent post](https://fortran-lang.discourse.group/t/computing-at-compile-time/3044/22) by @mecej4.

---

<div class="post-metadata">

**Author:** ![Jweber](https://avatars.discourse-cdn.com/v4/letter/j/e95f7d/32.png) [@Jweber](https://fortran-lang.discourse.group/u/Jweber)\
**Post date:** [March 27, 2022, 8:58pm UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/17 "2022-03-27T20:58:42Z")

</div>

Here my results for the 4 diffent Fortran codes of the comparison project

The original, non tweaked algorithm has been presented (for Python, C# and C++) in [https://www.youtube.com/watch?v=yYcHWGxtRQo&list=PLF2KJ6Gy3cZ5Er-1eF9fN1Hgw\_xkoD9V1&index=8](https://www.youtube.com/watch?v=yYcHWGxtRQo&list=PLF2KJ6Gy3cZ5Er-1eF9fN1Hgw_xkoD9V1&index=8)

The rules are explained in [Primes/CONTRIBUTING.md at drag-race · PlummersSoftwareLLC/Primes · GitHub](https://github.com/PlummersSoftwareLLC/Primes/blob/drag-race/CONTRIBUTING.md)

My non-faithful (it does not use classes) approach has been presented in the Fortran vs. Cobol comparison video, although there exists also faithful implementation by Thomas Jollans (github user tjol).  
I do not know, I guess because it has a rather “classic” Fortran look.

The considered compilers are:  
gfortran-7  
gfortran-8  
gfortran-9  
gfortran-10  
gfortran-11  
ifort 21.04  
ifx 21.04 beta  
aocc 3.1.0 based on flang 12.0

The test have been performed on an AMD Ryzen 7 3700X CPU (base frequency 2200 Mhz,  
max frequency 3600 MHz)

The numbers are the number of times the sieve algorithm is completed  
for the range up to 1000000 with 5 seconds

Notable results are:

- When a bitfiled is used, there are strong variations between different compilers  
(and different versions of gfortran). The variations increase for the object-oriented version

- The fastest code is generated if one 1-bit integer is used to store the state (prime/not prime)  
of a number (gain ~50% over the best bitfield results). There the results are more consistent than for the bitfield

- Storing the states of the numbers in an array of logical variables is slower than storing it in an 8bit integer and similar to the performance of a good bitfield implementation.

- Disclaimer: I do not believe that I really chose the optimal command line options

# solution\_1 One bit per digit (stored in int64 variables), not object oriented, shown in video

gfortran-7 -march=native -O3 -o benchmark-gcc-7 PrimesFortran.f08  
8905.2

gfortran-8 -march=native -O3 -o benchmark-gcc-8 PrimesFortran.f08  
11210

gfortran-9 -march=native -O3 -o benchmark-gcc-9 PrimesFortran.f08  
11211

gfortran-10 -march=native -O3 -o benchmark-gcc-10 PrimesFortran.f08  
11323

gfortran-11 -march=native -O3 -o benchmark-gcc-11 PrimesFortran.f08  
12417

Note: ifort -v results in ifort version 2021.4.0 ifort dors not recognize the .f08 suffix changed to .f90  
ifort -Ofast -march=core-avx2 -o benchmark-ifort-21.04 PrimesFortran.f90  
6097

ifx -Ofast -march=core-avx2 -o benchmark-ifx-21.04-beta PrimesFortran.f9  
7283

flang -march=native -O3 -o benchmark-flang-12.0 PrimesFortran.f90  
6659

# Object-oriented with bit array, fully meets the ‘faithful’ criteria of the comparison

gfortran-7 -march=native -O3 -oo-bitarray-gcc-7 prime-bitarray.f90  
12552

gfortran-8 -march=native -O3 -oo-bitarray-gcc-8 prime-bitarray.f90  
8199

gfortran-9 -march=native -O3 -oo-bitarray-gcc-9 prime-bitarray.f90  
8138

gfortran-10 -march=native -O3 -oo-bitarray-gcc-10 prime-bitarray.f90  
7613

gfortran-11 -march=native -O3 -oo-bitarray-gcc-11 prime-bitarray.f90  
12619

ifort -march=core-avx2 -O3 -oo-bitarray-ifort-12.04 prime-bitarray.f90  
2591.0

ifx -march=core-avx2 -O3 -oo-bitarray-ifx-12.04 prime-bitarray.f90  
2547

flang -march=native -O3 -oo-bitarray-flang-12.0 prime-bitarray.f90  
1412

# Object-oriented, one 8-bit Integer per number

gfortran-7 -march=native -O3 -oo-8bit-gcc-7 prime-8bit.f90  
18155

gfortran-8 -march=native -O3 -oo-8bit-gcc-8 prime-8bit.f90  
16597

gfortran-9 -march=native -O3 -oo-8bit-gcc-9 prime-8bit.f90  
17870

gfortran-10 -march=native -O3 -oo-8bit-gcc-10 prime-8bit.f90  
18029

gfortran-11 -march=native -O3 -oo-8bit-gcc-11 prime-8bit.f90  
18247

ifort -march=core-avx2 -O3 -oo-8bit-ifort-12.4 prime-8bit.f90  
18086

ifx -march=core-avx2 -O3 -oo-8bit-ifort-12.4 prime-8bit.f90  
18361

flang -march=native -O3 -oo-8bit-flang-12.0 prime-8bit.f90  
9651  
(Note: The values varied strongly between approx- 4000 and approx. 11000)

# Object-oriented, one Logical per number

gfortran-7 -march=native -O3 -oo-logical-gcc-7 prime-logical-array.f90  
12833

gfortran-8 -march=native -O3 -oo-logical-gcc-8 prime-logical-array.f90  
12764

gfortran-9 -march=native -O3 -oo-logical-gcc-9 prime-logical-array.f90  
12441

gfortran-10 -march=native -O3 -oo-logical-gcc-10 prime-logical-array.f90  
12453

gfortran-11 -march=native -O3 -oo-logical-gcc-11 prime-logical-array.f90  
12635.8

ifort -march=core-avx2 -O3 -oo-logical-ifort-12.4 prime-logical-array.f90  
13174

ifx -march=core-avx2 -O3 -oo-logical-ifort-12.4 prime-logical-array.f90  
13385

flang -march=native -O3 -oo-logical-flang-12.0 prime-logical-array.f90  
5573  
(Note: strong fluctuations of the results between ~3800 and ~8300)

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [March 27, 2022, 10:04pm UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/18 "2022-03-27T22:04:00Z")

</div>

> [@Jweber](#):
>
> The fastest code is generated if one 1-bit integer is used to store the state (prime/not prime)  
> of a number (gain ~50% over the best bitfield results).

I guess it is a _typo_ and should be 8-bit integer.

Still, as you noticed a few post above, the best C++ solutions does most of the calculations during the compilation (constant expressions), so it is sort of _cheating_. If this is also the case for the other 2 or 3 leaders (Lisp, D, maybe Rust), that would explain the _many-orders-of-magnitude_ difference between those and the rest of the competitors. It would require to sum compilation and execution times to make a fair comparison.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [March 28, 2022, 1:59am UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/19 "2022-03-28T01:59:16Z")

</div>

> [@msz59](#):
>
> … the best C++ solutions does most of the calculations during the compilation (constant expressions), so it is sort of _cheating_ . If this is also the case for the other 2 or 3 leaders (Lisp, D, maybe Rust) …

Yes almost all the leading contenders in this “drag race” from Zig to C++ achieve their performance via **compile-time computing**.

See this [**thread**](https://fortran-lang.discourse.group/t/user-defined-functions-in-constant-expressions/1509/2).

**CONSTEXPR as much as possible** has been a mantra with C++ and its derivatives such as D, Rust, Zig, etc. Folks such as Stroutsrup and De Rios et al. have presented a fair bit on the benefits of this, especially in systems programming. The results here are but one where their efforts show what is viable with the approach to compute once (during compilation) but to consume voraciously and efficiently i.e., use the values widely with great speed during runtime execution.

---

<div class="post-metadata">

**Author:** ![Jweber](https://avatars.discourse-cdn.com/v4/letter/j/e95f7d/32.png) [@Jweber](https://fortran-lang.discourse.group/u/Jweber)\
**Post date:** [March 28, 2022, 3:16am UTC](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038/20 "2022-03-28T03:16:13Z")

</div>

That was indeed a typo. I have corrected it.

[Next page](https://fortran-lang.discourse.group/t/79-languages-speed-competition-can-we-make-fortran-win/3038.md?page=2)
