I have a compute intensive loop parallelized using OpenMP:
!$omp parallel do
do j = 1, nc
!$omp end parallel do
The software I am developing uses a progress bar, and even with the parallelization the loop can be slow. I would like to insert a progress bar update into it. The progress bar works by checking how long a time has elapsed since it was last updated; if it is greater than a certain limit, then the update occurs via:
Is there any way of doing this?
The following is a simple hack:
! TitleProgressBar.f90 program TitleProgressBar use ifwin use omp_lib implicit none logical :: bResult integer, parameter :: MaxTitleLength = 200 character(len=*), parameter :: YourProgramTitle = "TitleProgressBar" integer :: i integer :: PercentDone, tick integer :: N bResult = SetConsoleTitle(YourProgramTitle) ! ... PercentDone = -1 ! -1 to display 0% done bar tick = 0 N=10000 !$omp parallel do do i = 1, N call doWork(i) !$omp atomic update tick = tick + 1 ! Race condition benign if((tick * 100) / N > PercentDone) then PercentDone = min((tick * 100) / N, 100) bResult = SetConsoleTitle(YourProgramTitle // ' [' // REPEAT('|',PercentDone) // REPEAT(' ', 100-PercentDone) // ']' // CHAR(0)) endif end do !$omp end parallel do bResult = SetConsoleTitle(YourProgramTitle) pause end program TitleProgressBar subroutine doWork(i) call sleepqq(mod(i,10)) end subroutine doWork
Try replacing the trailing space with CHAR(249)
Space and '|' are not nearly the same horizontal spacing, CHAR(249) is small center dot and approximates width of '|'
While you can do a Dialog box, this would add a thread. With a significantly more programming you can add a status bar to the console window and place a progress bar there.
Note, display visually stops at 99% (100% is immediately replaced by empty progress). You can change this by replacing the title at a later time (e.g. after you write results to file).
Also, if you wish, you could code with critical section (introducing delays) or have only one of the threads update (may be jerky but less overhead).
Presumably, if the doWork is moderately long, lines 25 and 26 may complete before a different thread notes the update.
You might consider using:
integer, volatile :: PercentDone
In the event that your doWork gets inlined, this would prevent PercentDone from being registerized.
By .NOT. using thread-safe update of PercentDone you are trading off a small probability of two (or more) threads updating the progress bar to the same value against the overhead of all threads going through a critical section (or other means of coordination) on every tick update. A bargain I presume.