【问题标题】:Fortran - writing to disk in columns by default?Fortran - 默认情况下按列写入磁盘?
【发布时间】:2018-01-18 19:26:30
【问题描述】:

我正在编写一个简单的代码来将一些大型矩阵输出到磁盘,这些矩阵随后将在 matlab 中读取。

我编写了以下代码,它举例说明了这样一个矩阵的编写。我关心两件事:

  1. 写入磁盘的效率(寻找不太慢的东西)
  2. 在 matlab 中很容易阅读

一个

PROGRAM WriteDisk

character(80)  :: filename = ' '    
INTEGER :: indt
INTEGER :: ind1, n1 = 161
INTEGER :: ind2, n2=20
INTEGER :: ind3, n3=2
INTEGER :: ind4, n4=2
INTEGER :: ind5, n5=21
INTEGER :: ind6, n6=20
INTEGER :: ind7, n7=2
INTEGER :: ind8, n8=2

INTEGER :: dummy    
REAL, ALLOCATABLE :: m1(:,:,:,:,:,:,:,:,:)
ALLOCATE(m1(2,n1,n2,n3,n4,n5,n6,n7,n8))   


dummy = 1

do ind8 = 1,n8
do ind7 = 1,n7
do ind6 = 1,n6    
do ind5 = 1,n5
do ind4 = 1,n4        
do ind3 = 1,n3        
do ind2 = 1,n2      
do ind1=1,n1    

    m1(2,ind1,ind2,ind3,ind4,ind5,ind6,ind7,ind8) = dummy
    dummy = dummy + 1

end do
end do
end do
end do
end do
end do
end do
end do

indt = 1
write(filename,'(a,i0,a)')'PF_m1_',indt,'.txt'    
OPEN(UNIT=25,FILE=filename,STATUS='replace',ACTION='write')
WRITE(25, *)  m1(2,:,:,:,:,:,:,:,:)
CLOSE(UNIT=25)



END PROGRAM

上面的程序将矩阵m1写成4327680 x 5。这使得在 matlab 中重塑它很麻烦(尽管完全可能),因为在 Matlab 中我需要执行以下操作:

也许我的问题不够清楚。当 Fortran 写入它写入的矩阵时,它包含 4327680 行和 5 列。 IE。当我在 matlab 中打开它时,我必须做一些事情,比如以原始格式获取矩阵:

n1 = 161;
n2 = 20;
n3 = 2;
n4 = 2;
n5 = 21;
n6 = 20;
n7 = 2;
n8 = 2;

m1 = load('PF_m1_1.txt'); %This is a two dimensional matrix that needs to be transposed and reshaped TWICE to get the original matrix
m1 = m1';
m1 = m1(:);
m1 = reshape(m1, n1,n2,n3,n4,n5,n6,n7,n8)

有没有办法把它写成一个单一的向量,其中元素 m1(2,1,1,1,1,1,1,1,1) 作为第一个元素,m1(2,2,1,1,1,1,1,1,1) 作为第二个元素,...,m1(2,end,end,end,end,end,end,end,end) 作为最后一个元素,等等?

或者无论如何我不知道,快速将其直接保存为.mat 文件?

【问题讨论】:

  • 如果你关心效率,就使用未格式化的I/O,否则你做不了什么。另外,AFAIK,Matlab 和 Fortran 一样是列专业的,你能解释一下为什么它们不兼容以及为什么 Fortran 顺序很麻烦吗?来自 Fortran 的高效 I/O 在这里处理了很多次,一遍又一遍地重复所有事情是没有意义的。
  • 值得注意的是,您要求的顺序正是 Fortran 默认使用的顺序。我不明白你的问题。
  • Fortran 将m1(2,1,1,1,1,1,1,1,1) 作为第一个元素,m1(2,2,1,1,1,1,1,1,1) 作为第二个元素!!!真的,有什么问题?
  • 嗨弗拉基米尔。也许我不够清楚。请参阅上面的编辑。我搜索了未格式化的 I/O,但似乎无法使用文件名?我可以在 stackoverflow 或其他论坛上找到有关高效 I/O 的大多数示例都处理 1 或 2 维矩阵,并且扩展到更高维空间似乎并非易事。
  • 您可以使用文件名,将其扩展到更高的维度很简单。

标签: matlab io fortran


【解决方案1】:

"有没有办法把它写成一个单一的向量,以元素 m1(2,1,1,1,1,1,1,1,1) 作为第一个元素,m1(2,2 ,1,1,1,1,1,1,1) 作为第二个元素,...,m1(2,end,end,end,end,end,end,end,end) 作为最后一个元素,等等?"

是的,这是默认的 Fortran 列主要顺序。这是您的文件已经写入的顺序。您无需做任何事情。

"这使得在 Matlab 中重塑它很麻烦(尽管完全有可能),因为在 Matlab 中我需要执行以下操作: m1 = reshape(m1, n1,n2,n3,n4,n5,n6,n7,n8)"

重塑只是更新内部描述符。这应该是一个非常快速的操作。完全可以忽略不计。即使需要洗牌,也比从硬盘读取要快得多。

“我关心两件事:1. 写入磁盘的效率(寻找不太慢的东西)”

使用未格式化(也称为二进制)I/O:

OPEN(UNIT=25,FILE=filename,ACCESS='stream',STATUS='replace',ACTION='write')
WRITE(25)  m1(2,:,:,:,:,:,:,:,:)
CLOSE(UNIT=25)

"2. 在 Matlab 中轻松阅读"

要从 Matlab 读取它,请从 Matlab 文档 https://www.mathworks.com/help/matlab/ref/fread.html 和大量其他资源中了解如何从 Read and write from/to a binary file in Matlab 读取二进制数据。

不要忘记告诉 Matlab 正确的尺寸。或者将维度存储在数据文件的第一个字节(标题)中。

【讨论】:

  • 好的。我可以理解 matlab 中的重塑速度很快。我仍然想避免这种情况,以使代码更加透明。另外,我需要进行两次重塑而不是一次。只是行 m1 = reshape(m1, n1,n2,n3,n4,n5,n6,n7,n8) 并没有提供与 Fortran 中相同的矩阵(请参阅上面的完整 matlab 代码)。它是否正确?关于您未格式化的评论,似乎我可以很容易地在 Fortran 中使用: OPEN(UNIT=25,FILE=filename,STATUS='replace',ACTION='write', form='unformatted') 但后来它变得非- 在 Matlab 中打开很简单。
猜你喜欢
  • 2014-12-16
  • 1970-01-01
  • 2017-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-08
  • 1970-01-01
  • 2012-02-29
相关资源
最近更新 更多