问题
I have developed a Fortran code which has the following characteristics:
- Global variables
- 13 Modules with multiple subroutines
- Independent subroutines
- Using Intel MKL library for LAPACK libraries (Linear Algebra)
- Reading and writing text files
The code has become quite big. Even though at this stage I am trying to get the correct answer, speed of execution of the code is desired.
I was writing a text log file with tags such as ERROR: message
or INFO: message
so far. But writing too much information slows down the code. I know in Java development we use log4j library to efficiently write log files where we can switch on or off various levels of logging. So once the code is clean, we can switch off low level logs and just keep the high level logs.
I would like to know from other programmers what is the best way to handle this in Fortran 90+.
回答1:
The easiest way would be to create an integer variable verbose
and read in its value at execution (from file or through command line). By doing this, you could create different levels:
- verbose = 0 => no output
- verbose = 1 => errors only
- verbose >= 2 => errors & info
It'd be simple to implement:
IF(verbose >= 1) CALL OutputError(message)
IF(verbose >= 2) CALL OutputInfo(message)
and so on.
回答2:
I'm using the following preprocessor macros for exactly this task (inside MACROS.h
):
#ifdef DEBUG
#define DWRITE write(*,*) __FILE__,__LINE__,
#define dwrite write(*,*) __FILE__,__LINE__,
#else
#define DWRITE !
#define dwrite !
#endif
In my code I then have the following header:
#define DEBUG
#include "MACROS.h"
...
dwrite 'An error occurred!'
This gives my the file and the line where the error occurred, and by commenting the first line I can easily switch the message on/off.
You could easily extend this to different debug levels and writing to files...
回答3:
I've seen people implement logging at the compiler level in a manner similar to Kyle Kanos's method with preprocessor directives. Not fortran standard, but I know it can be done with some fortran compilers.
回答4:
I've personally created a data type that contains a message
(character array) and a procedure pointer that handles the message. It's not the most efficient system, but the message is written to via write(io%message, fmt_statement) fmt_variables
, and then the procedure pointer is called, i.e. io%print(msgType, msgLog, message)
, for example io%print(error, debug, io%message)
.
type, private :: badLogger
character(128), private :: message = ""
! Note here that IO is an abstract interface elsewhere
! and that defaultPrint is some printing procedure that
! matches the IO interface
procedure(IO), private, pointer :: print => defaultPrint
end type badLogger
! Usage:
type(badLogger) :: io
write(io%message, *) "I love pizza!"
call io%print(comment, fun, io%message)
I've recently read of something called pFLogger
. The GitHub page for the project is https://github.com/Goddard-Fortran-Ecosystem/pFlogger/blob/master (see https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20170011091.pdf, https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20170011458.pdf), which seems very versatile at first glance. I haven't used it yet, but I'm definitely going to look into it!
Sorry for the severely delayed response! Hopefully this is still helpful to some!
来源:https://stackoverflow.com/questions/19523671/professional-fortran-code-development-log-file-creation