我试图在控制台屏幕上打印一些长迭代进度的指示符。具体来说,我希望在控制台屏幕上显示这样的内容:
----|----|----|----|这就是,每次迭代后打印- (不是5的倍数),在每次迭代之后打印|。这应该是实时发生的:每次迭代一个字符。
我尝试使用带有WRITE选项的ADVANCE='NO'语句,但是只在执行所有程序之后,或者在使用另一个带有ADVANCE='YES'选项的WRITE语句之后,才会在屏幕上显示所需的输出。
这是我的密码:
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子例程来模拟这样一个事实:每次迭代都需要大量时间。
发布于 2017-07-25 06:01:32
按照IanH和DannyVanpoucke关于刷新语句的建议,这是代码的一个版本,按预期工作:
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语句使缓冲区中的信息可用,这是Intel Fortran的一个特定问题。
发布于 2017-07-24 09:06:07
可以使用flush语句向写入文件的数据发出“可用”的信号。这句话的意思仍然是处理器依赖的,但通常你会从你的问题中得到你想要的行为。
flush语句需要一个单元号。对于输出到控制台,您可以使用OUTPUT_UNIT从ISO_FORTRAN_ENV。IntelFortran17.0和更早版本应该显示您想要的行为,对于当前的ifort,您还需要在写语句中使用OUTPUT_UNIT (这可能是编译器/编译器运行时的错误)。
(您还应该修复写语句中的语法错误。)
发布于 2017-07-24 12:44:32
确实,您的设置在理论上应该工作(考虑到不同编译器的不同行为等等)。上面建议使用刷新(索引)语句,使用与标准输出相关的索引,这甚至可以解决不同编译器之间的差异。然而,在某些环境中(更具体地说,集群和HPC-超级计算机),这仍然不能解决您的问题。当我自己实现了一个进度遇到同样的问题时,我得出了以下结论:
HPC系统可以在输出前对数据执行广泛的缓冲,以提高机器的效率(磁盘写入是最慢的内存访问选项)…。因此,这有时可以推翻我们的刷新命令。进度栏在实际完成之前不会显示出很大的进展,此时整个条形图将立即显示。有一些选项可以强制基础结构不使用此缓冲(系统管理员一般不会理解这一点),例如通过设置编译器标志-assume nobuffered_stdout。因此,HPC应用程序的最佳解决方案将是构造一个略为修改的进度条,其中不使用回车。
您可以很容易地通过在桌面上运行相同的代码来测试这一点,在桌面上,刷新语句将为您提供预期的行为。
https://stackoverflow.com/questions/45273123
复制相似问题