Geert Jan Bex

Geert Jan Bex

Since 2009 I'm an HPC consultant for the Flemish Supercomputer Center, doing support and training (also for PRACE and EuroCC). I've a PhD in physics and CS on topics in machine learning.

Location Belgium


  • @EstherBendewr This is a linking error (ld), the flow of the build process is that both the Fortran file that contains the definition of the module and the file that contains the program unit are compiled, producing object files (.o files). The next steps is to link those two object files into an executable. The CMake files take care of this, so I'm guessing...

  • Geert Jan Bex replied to [Learner left FutureLearn]

    @enricospecogna You can start with just the compiler. If you want to build the code in the repository, you will need CMake as well.

  • @AshwinKumar I'm not sure I get what you mean. For performance (and multithreading) it is certainly best to use a BLAS implementation (either OpenBLAS or MKL or ...). It would be nice if the compiler could replace a call to matmul by a call to BLAS, but that is wishful thinking.

  • @RajKumarPaudel I can't reproduce that with the code in the GitHub repo, so I'm assuming you implemented this yourself?

  • @ChienNguyen Pascal is a descendant of Algol. It predates (official) Fortran pointers by two decades as pointers where introduced in Fortran 90 (although there were some extensions of Fortran 77 that already supported pointers).

  • @AshwinKumar We read from 'data.txt', we write to standard output. If you open a file to read, you can not write to it, and vice versa. It is possible though to open a file so that you can read and write to it, and in some situations that is of course very useful. We will see examples of that later.
    The fort.1027238656 file is likely a core dump, i.e., the...

  • @ChienNguyen An or would also help.

  • @AshwinKumar For large matrices, a good BLAS implementation (OpenBLAS or Intel's MKL) is still useful though.

  • @JacobAbdelfatah Normally, the scalar has the same type as the elements of the array, but of course, you could use an integer scalar and multiply it with a real array. Here, <op> can be any arithmetic operator.

  • @JacobAbdelfatah The sequence attribute indicates that the compiler should generate user-defined types with the elements in the order specified in the code. If you don't specify sequence, the compiler can reorder the elements to make better use of memory alignment, which can improve the performance of your code. So sequence should only be used when you...

  • @JacobAbdelfatah Note that the 2 is in front of the A, so it means 2 strings (A) to be printed. The number in front of the format specifier is the number of times it is repeated.

  • @JacobAbdelfatah We are printing entire arrays, the * indicates that the formatting code that is specified after it will be used for all array elements, regardless of the length of the array.

  • @ChienNguyen I've added code that works for me to the repository (, does that work for you?

  • @ChienNguyen Indeed, you are right, thanks for pointing it out.

  • @JacobAbdelfatah Be careful though, C++ boolean operators are lazy, those of Fortran are not.

  • @JacobAbdelfatah There is a bool type with values true and false in C++, but indeed, under the hood it is still zero versus non-zero.

  • @ThomasWatson Indeed, a function returning void would be similar to a Fortran subroutine.

  • @ChienNguyen In which directory do you get this error?

  • @JulioMendez Some like the implicit loops, others don't. It depends on your background, I guess.

  • @ChienNguyen Fortran now has a block statement that allows for lexical scoping.

  • @ChienNguyen Do you have the Fortran compiler installed (i.e., gfortran)?

  • @ThomasWatson Probably yes, if you use make or CMake to build, it should be possible to configure VS Code (if you're brave enough ;)

  • @ChienNguyen It's a consequence of using * as a format specifier. My guess is that was done to prevent the output of consecutive output statements to be concatinated. If you want control, you have to use format specifiers.

  • @ChienNguyen You can use int to convert real to integer as well. However, I always make a mistake with cmplx when I've not used Fortran for a while.

  • @RolfRabenseifner Indeed, there is in week 5, when we discuss interoperability with other programming languages.

  • @MahmoudElbakly It protects you against mistakes, e.g., inadvertently modifying an argument's value and it provides information to the compiler for optimizations.

  • @MahmoudElbakly Yes and no. You can define a user-defined type so that the fields correspond to all the values you want to return from the function. Although your function returns a single value (an instance of that user-defined type), effectively, you return all the fields in that user defined type.

    You can also opt for a subroutine with multiple out or...

  • @LeonardClark My pleasure, I hope it was useful.

  • @LeonardClark Indeed, also memory bandwidth is used more efficiently.

  • @LeonardClark Indeed, there be dragons...

  • dpd

  • @IvanGirault You could use a preprocessor for that. It is not as clean as C++ templates, but it would get the job done.

  • @WolfT There is quite some information on object-oriented programming in Fortran.

  • @LeeH Indeed, end can be easier on the eyes than pairs of curly braces and less error-prone than whitespace.

  • It shows it roots

  • @JulioMendez Thanks, glad you enjoy it.

  • @JulioMendez Indeed, Bjarne Stroustrup made quite a few remarks on Fortran versus C++. The following article dates to 2007, and C++ has made quite a lot of progress since then, but still:

  • @JulioMendez Indeed they are. In fact, in Fortran speak, a procedure is either a function or a subroutine. This text was copied from another, older MOOC where I used the term function to denote both functions and subroutines since that MOOC was for both Fortran and C/C++ programmers.

  • @NoelAllapatt You'll have ample opportunity to get your hands dirty at the end of each week.

  • @StephenRoesner I appreciate (and use) good documentation. How much time to spend on writing documentation yourself depends on the target audience. However, experience learns that it is very unpleasant to have to document a large project after it has been completed, so it may pay to document important functions/key API while developing anyway.

  • @StephenRoesner Indeed, that will be discussed in detail later on as well.

  • @LucasPacheco For performance, runtime polymorphism is to be avoided. As long as the compiler can figure out which procedures to call, there is no performance impact. If that has to be decided at runtime, it will decrease efficiency.

  • @StephenRoesner Indeed, for many programming languages, the convention is to use uppercase for constants.

  • @云天燕 Apologies about that. We don't have any Chinese speakers in our team, so it would be very hard to check the quality when we would ask for translations.

  • It refers to the section on dynamic memory management. So if you allocate an array of the size provided by the user and that fails, the error message should be informative, i.e., read something like "specified vector size is too large".

  • @JulioMendez pA is the address of the "old" data. pA_new is the address of the new data. In the first iteration t = 1, the computation modifies the contents of A_new based on the content of A. At the end of that iteration, pA and pA_new are swapped, i.e., pA now points to A_new, and pA_new now points to A.
    In the second iteration t = 2, the data that...

  • @JulioMendez The point is that with pointers (pun intended) you don't have to copy the data. Given that copying the data is bound by the memory bandwidth (it has to move from RAM to CPU and back to a different location in RAM) that will take time. When you swap pointers, nothing gets copied, so no memory accesses, no roundtrip to RAM.

  • The semantics of pointers is not really different from that of other variables with respect to the values they have, "addresses" in this case. In languages such as C or C++ this is very clear since the assignment operator is used, the same one for "ordinary" values as for addresses. Fortran makes a difference because pointer "assignment" has its own...

  • @JulioMendez Pointers are (at the end of the day) simply addresses of data in memory, so besides the 64 bit that a pointer takes to store an address, there is no memory overhead. That said, the compiler may not be able to do certain optimizations when dealing with pointers as compared to arrays, so some code may be less efficient with respect to computational...

  • @JulioMendez The value attribute implies call by value, for scalar arguments, it would be roughly equivalent to intent(in).

    The integer (0-255) you pass via stop is the exit status of the application. The semantics is that 0 implies success. non-zero means some problem, the specific number can be used to convey the nature of the problem, e.g., 1 means...

  • It is mostly correct, but not always. If the size of an array is known at compile time, the compiler can generate more efficient code (loop unrolling can be precise and doesn't have to take into account edge cases).
    Also if allocated memory is used together with pointers, some optimizations can not be performed safely, so the compiler won't do...

  • The Fortran runtime has its own garbage collector. When an allocated array goes out of scope, the array is deallocated (at least when that happens in the same compilation unit). Personally I prefer to do deallocation just to make sure.
    When the application terminates, it is the OS that will do the cleanup.

  • I'd suggest having a look at the complete source code. That makes it probably easier to follow the text. You will find it in the GitHub repository.

  • @CesarGuerra Thank you :) Enjoy teaching your course.
    I teach a course on computational physics myself, although I use C++ for that (I have to confess).

  • @CesarGuerra The __FILE__ and __LINE__ macros are handled by the preprocessor, not the compiler itself, so you would either have to invoke the preprocessor, or, better, ensure that it gets invoked by the compiler by using .F90 (or .F03, ...) as a file extension. It works at least for gfortran (GCC) and ifort (Intel). I suspect most compilers will call a...

  • @CesarGuerra This brings us to the interesting topic of functional programming and monads. You could consider returning a user defined type that has the result as one element, and the status as another. This would allow you to write this as an elementary function. However, the resulting data structure would not be very efficient. You'd also have to deifne...

  • @JulioMendez I'd argue that in CMake you specify *what* you want, while in make files you specify how you want it done. In other words, CMake is descriptive, make is imperative. CMake will create a bunch of make files that contain the how, and as a developer you don't have to worry about that, because CMake knows how to do things when you specify what you...

  • @JulioMendez Think of a module that is has function for linear algebra, that could be useful in an application for computational fluid dynamics, but also in one for text retrieval.

  • @GuusLöhlefink Glad you enjoyed it, it was nice interacting with you.

  • @GuusLöhlefink They are entirely different things. OpenMP is intended for shared memory programming, so the application runs on a single compute node. MPI is a library for message passing, applications that use it consist of processes that can run on many compute nodes, exchanging data and state by sending messages around.
    In practice, if you have really...

  • @GuusLöhlefink That takes me back a very long time. I remember reading about it, it was quite enticing. I don't think I ever got hold of a compiler for it though.

  • @GuusLöhlefink Indeed, but the nice thing is that you get a multidimensional view on it.