-
Notifications
You must be signed in to change notification settings - Fork 188
Logger safe async io #245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Logger safe async io #245
Conversation
Added a blank to the output afer a comma. [ticket: X]
Added one line to the index referencing stdlib_logger.html. [ticket: X]
Documented changes in stdlib_logger.f90. Among them: 1. Additions of buffer and len_buffer to the logger type 2. Changes of self from intent(in) to intent(inout) in several procedures 3. Allowing new_line call in messsage string [ticket: X]
Numerous changes to src/stdlib_logger.f90: 1. Changed `Rrea_...` to `read_...` 2. Shortened several long lines, mostly those longer than 80 characters 3. Added buffer and len_buffer to logger_type(?) 4. Changed output so that instead of multiple writes of individual strings there is a single write of a single string formatted by inserting new_line calls. [ticket: X]
Changed indexing of the self % buffer from 0 based to the proper 1s based, and eliminated some unused variables. [ticket: X]
[GH Workflow set environment variables](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#environment-files)
@14NGiestas if your fix for docs build works, can you submit it as a separate PR? Then we can merge it and rebase this PR to master so that the docs build. |
It is already a separate PR #246. I'm just waiting the CI to finish. |
Co-authored-by: Ian Giestas Pauli <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two small issues discovered while testing the changes... There are still a few issues that I will try to solve.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Issue: the end of a string with indent=.true.
was not printed correctly.
The 3 proposed suggestions should solve this issue properly.
Changed log_error and log_io_error similarly 1. Added dummy character variable of len 28 and used it to hold stat/iostat string representation or lack thereof. 2. Changed suffix to allocatable len character variable and used it to hold the combined stat/iostat and errmsg/iomsg string representations or lack thereof. 3. Eliminated the trim of suffix as unneeded. 4. Eliminated unit and passed -999 directly to handle_write_failure. 5. For log_io_error changed procedure_name to 'log_io_error'. [ticket: X]
I have committed and pushed fixes for the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes sound good to me. Thank you @wclodius2 for these improvements!
IMO, this PR could be merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @wclodius2, I tested the changes locally.
Is it feasible to add a test that confirms that it's indeed async I/O safe? As I understand how this is implemented--write multi-lines into a character string, then write it to output in a single write statement--it should work as advertised. But a test program would help ensure this. What do you think?
Do you expect that this is async I/O safe also for SPMD programs using MPI or coarrays? Specifically, in a pattern where multiple processes are logging to the same file, or stdout. Granted, a safer programming pattern in this case would be for each process to write to its own dedicated logger file. Should we make note of this in the docs?
Would an OpenMP do loop with a logger do the trick? I have a similar example in one of my codes, however I put the logger in a critical OMP section with the first implementation. |
While a test would be useful I don't know how to write it. Parallel programming was not in demand for my work. In particular, how do we ensure that asynchronous calls aren't accidentally synchronous? Do we want to special case the cmake compiler flags and Makefile.manual flags for A note to the effect of "While every effort has been made to make the code thread and asynchronous I/O safe, it is always best to have each process write to its own dedicated logger file" might be useful. On a related note, should I add an |
Could such a test be satisfying, assuming that most compilers support basic OpenMP directives? ...
type(logger_type) :: logger
character (len = 30) :: cdumy
...
call logger % add_log_file( 'log.txt')
call logger % configure(indent = .true., time_stamp = .true.)
....
!$omp parallel default(none) shared(logger)
!$omp do
do i = 1, 100
!$ write(cdummy, '(i0)') omp_get_thread_num()
!$omp atomic
call logger % log_message( ' Message from thread '//trim(cdummy) )'
enddo
!$omp end do
!$omp end parallel
.... Such a test would be more about thread then asynchronous safety.
IMO it is a good idea to add it in the specs, especially if we claim it should asynchornous/thread/process-safe.
It would be good indeed. Probably it is best to do it in another PR independent from this one. |
@wclodius2, I agree. Do you mind adding this note in the spec document where you find it most appropriate? I think this will then be good to merge. |
Added the sentence "While every effort has been made to make the code thread and asynchronous I/O safe, it is always best to have each process write to its own dedicated logger file." [ticket: X]
I have added the sentence to @jvdp1 I have no experience with Open MP. My gut feeling is that an additional test wouldn't hurt, but it should probably be written by you as a separate PR. Things to think about if you should decide to do it.
|
Does this PR handles access to the buffer from different threads? Because having a buffer string without guarding the critical region does not guarantee one thread will not overwrite the buffer while the other thread was writing. I need to review the code to better understand that, but I belive It's up to the user put the logger call in a guarded region (omp critical, for e.g.). |
@wclodius2 I will propose another test later, when this is merged.
Good point. No, there is no guarding within Note that this issue should not apppear in MPI/coarray-type programs. |
Added Jeremies revision of the discussion in stdlib_logger.md. [ticket: X]
@14NGiestas FWIW the string buffer is in a logger object, and not a module variable. With a little extra work it could be made a procedure variable. |
FWIW with my latest push five of six CI/Builds passed. The one that failed "CI / Build (macos-latest, 9) (pull_request)" failed in running |
I tested it on my computer (Fedora) with gfortran 9.3.1, and there were no issues. |
FWIW the Mac OS run that fails uses |
I tested it again on my computer with different compilers and debug options. It always passed the tests! So no idea... |
While every effort has been made to make the code process and | ||
asynchronous I/O safe, it is always best to have each process write to | ||
its own dedicated logger file. | ||
For thread parallelism (e.g., with OpenMP), it is advised to put the | ||
logger call in a guarding region (e.g., in an OpenMP critical region). | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@milancurcic
Are you satisfied with this note that covers multi-thread and multi-process programs? If yes, I am ok to merge this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I'm happy with it so I'll go ahead and merge. Thank you all.
Changes in four files:
doc/specs/index.md
- addedstdlib_logger.html
to the index;doc/specs/stdlib_logger.md
- described the changes instdlib_logger.f90
;src/tests/logger/test-stdlib_logger.f90
- added a blank after a comma in the output;src/stdlib_logger.f90
- numerous changesnew_line
calls in the message string properly (added by @jvdp1, but undocumented instdlib_logger.md
)logger_type
and alen_buffer
integer to track the number of active characters in the buffer;new_line
in the output string, in order to make the output thread and asynchronous IO safe;Rrea_only_error
toread_only_error