我试图在控制台屏幕上打印一些长迭代进度指示器。具体来说,我希望在控制台屏幕上显示这样的内容:
----|----|----|----|
这是,在每次迭代后打印-
(不是5的倍数),并在每5次迭代后打印|
。这应该是实时发生的:每次迭代一个字符。
我尝试将WRITE
语句与ADVANCE='NO'
选项一起使用,但所需的输出仅在执行完所有程序后显示在屏幕上,或者在我使用另一个WRITE
语句后显示使用ADVANCE='YES'
选项。
这是我的代码:
PROGRAM TEST
IMPLICIT NONE
INTEGER :: i
DO i = 1,20
CALL SLEEP(2)
IF (MOD(i,5).EQ.0) THEN
WRITE(*,'(A)',ADVANCE='NO'), '|'
ELSE
WRITE(*,'(A)',ADVANCE='NO'), '-'
END IF
END DO
END PROGRAM TEST
我使用SLEEP
子例程来模拟每次迭代需要花费大量时间的事实。
答案 0 :(得分:2)
flush语句可用于表示已写入文件的数据“可用”。该陈述的含义仍然依赖于处理器,但通常你会得到你想要的问题。
flush语句需要一个单元号。要输出到控制台,您可以使用ISO_FORTRAN_ENV中的OUTPUT_UNIT。然后,英特尔Fortran 17.0及更早版本应显示您想要的行为,对于当前的ifort beta,您还需要在write语句中使用OUTPUT_UNIT(这可能是编译器/编译器运行时错误)。
(您还应修复WRITE语句中的语法错误。)
答案 1 :(得分:1)
确实,您的设置理论上应该可行(考虑到不同编译器的不同行为等)。上面使用FLUSH(索引)语句的建议,使用与标准输出相关的索引,甚至可以解决不同编译器之间的差异。但是,在某些环境(更具体地说是群集和HPC超级计算机)中,这仍然无法解决您的问题。虽然implementing a progress-bar myself我遇到了同样的问题,但我得出以下结论:
HPC系统可能在输出之前执行大量数据缓冲,以提高机器的效率(磁盘写入是最慢的内存访问选项)......因此,这有时会否决我们的flush命令。反过来,进度条在实际完成之前不会显示太多进展,此时整个条形图将立即显示。有一些选项可以强制基础设施不使用此缓冲(并且系统管理员通常不会理解这一点),例如通过设置编译器标志 -assume nobuffered_stdout 。因此,HPC应用程序的最佳解决方案是构建略微修改的进度条,其中不使用回车。
您可以通过在桌面上运行相同的代码轻松测试,FLUSH语句将为您提供预期的行为。
答案 2 :(得分:0)
根据IanH和DannyVanpoucke关于flush语句的建议,这是一个按预期工作的代码版本:
PROGRAM TEST
IMPLICIT NONE
INTEGER :: i
DO i = 1,20
CALL SLEEP(2)
IF (MOD(i,5).EQ.0) THEN
WRITE(UNIT=6,FMT='(A)',ADVANCE='NO'), '|'
FLUSH(UNIT=6)
ELSE
WRITE(UNIT=6,FMT='(A)',ADVANCE='NO'), '-'
FLUSH(UNIT=6)
END IF
END DO
END PROGRAM TEST
正如问题下面的一些评论所指出的,似乎需要使用flush语句使缓冲区中的信息可用是英特尔Fortran特定的问题。