Fortran与matlab在数组上的对比.docx
《Fortran与matlab在数组上的对比.docx》由会员分享,可在线阅读,更多相关《Fortran与matlab在数组上的对比.docx(12页珍藏版)》请在冰豆网上搜索。
Fortran与matlab在数组上的对比
Fortran与matlab在数组运算上的对比
航院力9金鹏2009011622
Fortran与matlab均是数值计算中的有力的工具。
前者以效率著称,后者以灵活出众。
二者在矩阵运算上很有特色,“matlab”更是矩阵实验室的简称。
二者在矩阵运算上,自然值得一比。
首先最简单的一个是生成随机矩阵并作矩阵乘法的速度对比。
Fortran中:
programcpr
implicitnone
integer,parameter:
:
n=300
real(8)a(n,n),b(n,n),c(n,n)
integeri,j
real(8)t1,t2,t
callcpu_time(t1)
callran_matrix(a)
callran_matrix(b)
callcpu_time(t2)
print*,t2-t1
c=matmul(a,b)
callcpu_time(t2)
print*,t2-t1
!
print*,a
contains
subroutineran_matrix(a)
implicitnone
real(8)a(n,n)
integeri,j
real(8)r
callrandom_seed()
doi=1,n
doj=1,n
callrandom_number(r)
a(i,j)=10000*r
enddo
enddo
endsubroutineran_matrix
endprogram
加上注释,共有40行。
运行结果如下图:
对于MATLAB中,程序代码:
tic;t1=clock;a=rand(300,300);b=rand(300,300);c=a*b;toc;t2=clock;t=t2-t1;
只用一行,其中包括了8句语句,为Fortran的1/5。
结果显示:
Elapsedtimeis0.015592seconds.
t=0.016
当然,有时也有:
Elapsedtimeis0.022325seconds.
上下浮动相当大。
在debug状态下,fortran的效率并没有体现出来明显的优势,甚至还更慢。
但是,在relaese状态下:
多次运行保持不变
让MATLAB与Fortran的效率作对比,几乎可是说没有可比性,如果让Fortran与MATLAB在图形显示尤其是三维图形的显示上对比,也是如此。
数组操作上的对比,我想可以赋值和引用上来说明。
刚才已经进行了对矩阵处理速度的粗糙对比(同时也是Fortran中对DEBUG与RELEASE状态的对比)。
一、赋值操作
在一般的语言中,对数组的操作都会有对具体元素的操作,所以其他的操作方式才跟值得一比。
在Fortran语言中,要使用变量要首先进行声明,矩阵亦即多维数组更不例外。
声明方式有:
real(4)d(3:
1,2:
7)
integera(3,5)
dimension:
:
e(10),f(2,3)
而在MATLAB中,无须声明,直接使用即可。
Fortran赋初值技巧:
real(4):
:
b(2,2)=(/1.0,2.0,0.0,4.0/)!
用数组构造器赋值
datab/1.0,2.0,0.0,4.0/
datai/-1/,f/1,2,2*0,3,4/!
按列存储,*表示重复
dataa/1:
5/
dataa(1:
3)/3*1/
dataa(1:
4)/3*-1,2/
以上方法均在声明阶段进行。
此外还有条件赋值,十分方便:
Where(i>j)a(I,j)=2
Elsewhere(i==j)a(I,j)=1
Endwhere
Forall(a>0)a=0
相应的,对于MATLAB,可以有逻辑寻址对应Fortran中的相应功能:
x(abs(x)>1)
%返回数组x中绝对是大于1的元素组成的一维数组。
abs(x)>1则返回一个逻辑数组
另外,Fortran的merge函数也可实现类似的功能,只是相比之下写起来十分罗嗦。
当然如果使用操作符重载,可以简化书写,但是可移植性会比较差,而且增加了编程的复杂程度,为了简化的复杂化,有点得不偿失。
对于数字整体操作,在实现同样的功能的时候,Fortran利用了并行处理的能力,而MATLAB却要多消耗掉形状相同的数组那么大的内存资源,MATLAB其灵活性让人一目了然,Fortran的高效性则在代码背后隐藏着:
Integera(5)
a=1
a=[1:
5]
a=[5:
1:
-1]
c(2:
5)=c(1:
4)%此时是整体操作,引入不必担心先赋值的影响到后边的数着
对于Fortran和MATLAB,均可以进行整体赋值:
对于矩阵A,将所有元素置为3的语句为:
Fortran中
A=3
A(1:
3,1:
3)=3
MATLAB中
A(1:
3,1:
3)=3
其他情况,
a=[123;456]
a=[123
456]
或者可以利用其他量赋值:
a=[123];b=[456];c=[a;b];d=[a'b']
另外,对于等差情况还可以
X=(0:
0.1:
1)*pi%fortran中的三元下标虽然跟这个有所区别,但是在使用是差不多
X=linspace(0,10,10)
又是需要取对数坐标的
X=logspace(0,2,11)
对于linspace,logspace都有三个参数依次为起始数值,终了数值,和数据点个数。
这种功能在Fortran中似乎没有与相对应的方式。
MATLAB的高维情况,也是直接赋值作为声明:
>>b(3,3,3,3)=9
b(:
:
1,1)=
000
000
000
b(:
:
2,1)=
000
000
000
b(:
:
3,1)=
000
000
000
b(:
:
1,2)=
000
000
000
b(:
:
2,2)=
000
000
000
b(:
:
3,2)=
000
000
000
b(:
:
1,3)=
000
000
000
b(:
:
2,3)=
000
000
000
b(:
:
3,3)=
000
000
009
MATLAB用这种复杂但是有效的方式显示出b的值。
当然,高维数组应该尽量少用,也要合理利用。
Fortran的高位数组支持的到7维,仍然是声明后使用。
而在MATLAB中,
a(1,1,1,1,2,2,2,2,2,2,1,2)=1%若没有写上=1则会出现错误。
的时候,竟然也没有出现错误提示,大量的篇幅用来显示同样的语句a(:
:
1,1,2,2,2,2,2,2,2,2)=
0
当然这只是在数组中只有很少的元素(1~3个)的情况下。
用这么高的维数做运算明显不是明智的。
这种情况下,数组应与稀疏矩阵的优化有所联系,因此MATLAB可以胜任。
我也没有查到一个确切的维数的限制,但是至少知道数组大小的由内存所决定了。
可以用memory查询一下:
>>memory
Maximumpossiblearray:
752MB(7.890e+008bytes)*
Memoryavailableforallarrays:
1496MB(1.569e+009bytes)**
MemoryusedbyMATLAB:
290MB(3.038e+008bytes)
PhysicalMemory(RAM):
1908MB(2.001e+009bytes)
*Limitedbycontiguousvirtualaddressspaceavailable.
**Limitedbyvirtualaddressspaceavailable.
一些已经有的向量的运算
min
max
mean
median%中位数
std%标准差
diff%相邻元素差
sort%排序,而且返回索引
sum
prod
cumsum%累计元素总和
cumprod%累计元素总乘积
dot
cross
对于某一些特殊的矩阵,MATLAB自带函数进行赋值,例如:
ones(m,n)
eye(m,n)
magic(m)
rand(m,n)
randn(m,n)
pascal(n)
cat(k,a,b)%用于合并矩阵,也算在赋值了
vander(m,n)
hilb(n)
一些操作:
flipud%上下翻转
fliplr&左右翻转
rot%旋转矩阵
自带的丰富的函数,节约了大量的编程的时间。
对于异质数组cell数组,不展开了。
二、查询数组形状及对数组元素的引用
对于矩阵的操作应该说Fortran与MATLAB各有各的精彩。
当然,就方便而言,从我的了解来看应该还是MATLAB更胜一筹。
方法之多样,方式之灵活,MATLAB简直让我眼花缭乱。
首先对比关于数组一些信息的获取:
Fortran
MATLAB
数组上(下)界
ubound(a)(lbound(a))
lendth
形状
Shape(a)
元素个数
Size(a)
占用内存大小
Sizeof(a)
whos
然后从引用或者寻址。
Fortran的引用可以有这样一些方式:
A(n,m)
A(:
n)
A(1:
3,m)
A(2:
ubound(a,1),n)!
相应的MATLAB的语句为a(2:
end,n),之前几种用法基本一致
C=A(b)!
即利用两个数组给第三个数组赋值,MATLAB中亦有如此用法。
运算中,数组均可以作为参数:
y=sin(x)
在数组中,个人觉得MATLAB比Fortran最大的特色在于它的缩维操作:
A(2,:
)=[]
当然,如果只置空了行或者列的某一部分时,无法缩维。
缩维操作给MATLAB的编程人员留下优化内存使用的空间,方便灵活,Fortran里如果想更灵活的运用内存,则恐怕只能向链表求助。
另外更下策的办法如果让Fortran做同样的事情,应该用可调大小数组通过allocate和deallocate的反复操作,而且应该还要一个足够大的中间数组才能进行。
对于追求效率的Fortran来讲,这是无法想象的。
而MATLAB则以这种灵活性。
在避免数组使用的情况下计算相图轨线的坐标时,
Fortran:
programgraph
implicitnone
realtime0,time1
integer,parameter:
:
m=35000
real,parameter:
:
a=0.25
real,parameter:
:
b=1
real,parameter:
:
c=3
realt,gap
realx,y,z
realx1,y1,z1
integer:
:
i,err=0
callcpu_time(time0)
x=0;
y=0;
z=0.989876;
open(1,file='graph.txt',form='formatted',status='replace')
if(err)print*,'wrong!
'
t=30000/m
doi=1,m
x1=x
y1=y
z1=z
x=x1-t*(y1+z1)
y=y1+t*x1+a*y1*t
z=z1+(b+z1*(x1-c))*t
write(1,*)x,y,z
enddo
close
(1)
callcpu_time(time1)
print*,time1-time0
end
生成了一个1.56M的文本格式数据文件。
不过方程组的答案趋于无穷,文件中的数值没迭代几次就都是无穷了,显示为NaN。
MATLAB:
tic;
m=35000;
figure(3)
t=linspace(0,30000,m);
g=30000/m;
x=0;
y=0;
z=0.989876;
a=0.25;
b=1;
c=3;
fork=1:
m
x1=x;
y1=y;
z1=z;
x=x1-g*(y1+z1);
y=y1+g*x1+a*y1*g;
z=z1+(b+z1*(x1-c))*g;
holdon
%plot3(x,y,z)
end
%gridon
toc;
运行时间显示:
Elapsedtimeis8.816268seconds.
如果加上画图的时间:
Elapsedtimeis39.565406seconds.
远远大于Fortran。
如果试图把中间生成的数据用数组记录下来,内存在运行了好久之后,溢出了。
稍微集中一些比较常用的MATLAB中关于线性代数的矩阵操作的函数:
det行列式
norm矩阵或者向量的范数
null矩阵的核零子空间
orth正交基底
rank秩
subspace子空间的夹角
trace迹
expm矩阵指数函数
funm矩阵一般函数
logm矩阵对数函数
sqrtm矩阵开平方
/\用于解方程组
cholcholesky分解
choline不完全的cholesky分解
cond条件数,测试接近奇异的程度
condest估计
inv逆矩阵
luLU分解
luinc不完全LU分解
qrQR分解
lscov已知covariance的最小二乘法
nnls非负的最小二乘法
对于数组和矩阵上的一些运算,MATLAB显得十分方便。
在此不再详细展开。
MATLAB选择“牺牲资源”“提高效率”,但是实际上对内存的频繁操作并没有带来效率上的出色,而Fortran以其严谨的逻辑与明确的规定书写提高着效率,但是带来的了编程时的繁琐。
对于大型的计算,Fortran是当之无愧的第一选择。
在数组的操作上,Fortran呵呵MATLAB均有十分出色的表现。
MATLAB方法多。
可以利用很简单的代码完成Fortran需要花很多功夫才能编出来的程序。
但是MATLAB的所有元素均用数组来存储,尤其是cell数组更是奇特。
Fortran则严格明确,同时又在较为丰富的矩阵操作中相当好的利用了并行计算的硬件资源。
二者都是计算编程人员强有力的工具。