【发布时间】:2016-02-09 21:06:44
【问题描述】:
tl;dr:我发现在某些情况下“隐式执行”写入比显式写入慢,并且想了解为什么/如果我可以改进这一点。
详情:
我有一个代码可以起到以下作用:
DO i=1,n
calculations...
!m, x, and y all change each pass through the loop
IF(m.GT.1)THEN
DO j=1,m
WRITE(10,*)x(j),y(j) !where 10 is an output file
ENDDO
ENDIF
ENDDO
输出文件最终变得相当大,所以看起来写作是一个很大的性能因素,所以我想优化它。在任何人问之前,不,由于各种下游要求,远离 ASCII 不是一种选择。因此,我将IF 语句(和内容)重写为:
IF(m.GT.1)THEN
!build format statement for write
WRITE(mm1,*)m-1
mm1=ADJUSTL(mm1)
!implied do write statement
WRITE(10,'('//TRIM(mm1)//'(i9,1x,f7.5/),i9,1x,f7.5)')(x(j),y(j),j=1,m)
ELSEIF(m.EQ.1)THEN
WRITE(10,'(i9,1x,f7.5)')x(1),y(1)
ENDIF
这会根据要写入的值 # 构建格式语句,然后执行单个写入语句来输出内容。我发现使用此公式的代码实际上运行速度较慢。作为参考,当要写入的数据量固定时,我已经看到在同一系统(硬件和软件)上执行隐含的 do write 语句时的显着加速。假设 WRITE 语句本身更快,那么这将意味着构建该语句的几行的开销是需要额外时间的,但这似乎很难相信。作为参考,m 可以变化很大,但可能平均至少为 1000。字符串的串联// 是一个非常慢的运算符,还是我还缺少其他东西?提前致谢。
【问题讨论】:
-
如果你只使用
write(10,'(i9,f8.5)') (...)并依赖格式转换呢? -
Ore 使用
*作为乘数,或者像 999999 这样的大数。 -
实际的输出格式有更多的值,这样
*可能会导致不需要的换行。但是,我不知道 francescalus 的不指定方法或 VladimirF 的仅使用始终大于m的数字是有效的选项。我会试用并更新。 -
@TTT,我相信 Vladimir F 对
*的使用是作为无限重复计数说明符(参见 F2008)而不是列表导向输出。所以,你会得到write(10,'(*(i9,1x,f7,5,:,/))')(我建议的冒号)。 -
@francescalus 啊,我误解了,虽然我也没有注意到那个选项。这与您提供
write(10,'(i9,f8.5)') (...)的想法有什么区别吗?也许如果指定了ADVANCE='NO'?
标签: performance io fortran