1、Fortran与matlab在数组上的对比Fortran与matlab在数组运算上的对比航院 力9 金鹏 2009011622Fortran与matlab均是数值计算中的有力的工具。前者以效率著称,后者以灵活出众。二者在矩阵运算上很有特色,“matlab”更是矩阵实验室的简称。二者在矩阵运算上,自然值得一比。首先最简单的一个是生成随机矩阵并作矩阵乘法的速度对比。Fortran中:program cprimplicit noneinteger ,parameter:n=300real(8) a(n,n),b(n,n),c(n,n)integer i,jreal(8) t1,t2,tcall cp
2、u_time(t1)call ran_matrix(a)call ran_matrix(b)call cpu_time(t2)print*, t2-t1c=matmul(a,b)call cpu_time(t2)print*, t2-t1!print*, acontains subroutine ran_matrix(a) implicit none real(8) a(n,n) integer i,j real(8) r call random_seed() do i=1,n do j=1,n call random_number(r) a(i,j)=10000*r enddo enddo
3、end subroutine ran_matrixend program加上注释,共有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。结果显示:Elapsed time is 0.015592 seconds.t=0.016当然,有时也有:Elapsed time is 0.022325 seconds.上下浮动相当大。在debug状态下,fortran的效率并没有体现出来明显的优势,甚至还
4、更慢。但是,在relaese状态下:多次运行保持不变让MATLAB与Fortran的效率作对比,几乎可是说没有可比性,如果让Fortran与MATLAB在图形显示尤其是三维图形的显示上对比,也是如此。数组操作上的对比,我想可以赋值和引用上来说明。刚才已经进行了对矩阵处理速度的粗糙对比(同时也是Fortran中对DEBUG与RELEASE状态的对比)。一、 赋值操作在一般的语言中,对数组的操作都会有对具体元素的操作,所以其他的操作方式才跟值得一比。在Fortran语言中,要使用变量要首先进行声明,矩阵亦即多维数组更不例外。声明方式有: real(4) d(3:1, 2:7) integer a(
5、3,5) dimension: e(10), f(2,3)而在MATLAB中,无须声明,直接使用即可。Fortran赋初值技巧: real(4): b(2,2) = (/1.0, 2.0, 0.0, 4.0/) !用数组构造器赋值 data b /1.0, 2.0, 0.0, 4.0/ data i /-1/, f /1, 2, 2 * 0, 3, 4/ ! 按列存储, *表示重复 data a /1:5/ data a(1:3) /3 * 1/ data a(1:4) /3 * -1, 2/ 以上方法均在声明阶段进行。此外还有条件赋值,十分方便: Where(ij) a(I,j)=2 Els
6、ewhere(i=j) a(I,j)=1 End where Forall(a0) a=0相应的,对于MATLAB,可以有逻辑寻址对应Fortran中的相应功能:x(abs(x)1) %返回数组x中绝对是大于1的元素组成的一维数组。abs(x)1则返回一个逻辑数组另外,Fortran的merge函数也可实现类似的功能,只是相比之下写起来十分罗嗦。当然如果使用操作符重载,可以简化书写,但是可移植性会比较差,而且增加了编程的复杂程度,为了简化的复杂化,有点得不偿失。对于数字整体操作,在实现同样的功能的时候,Fortran利用了并行处理的能力,而MATLAB却要多消耗掉形状相同的数组那么大的内存资源
7、,MATLAB其灵活性让人一目了然,Fortran的高效性则在代码背后隐藏着:Integer a(5)a=1a=1:5a=5:1:-1c(2:5) = c(1:4) %此时是整体操作,引入不必担心先赋值的影响到后边的数着对于Fortran和MATLAB,均可以进行整体赋值:对于矩阵A,将所有元素置为3的语句为:Fortran中A=3A(1:3,1:3)=3MATLAB中A(1:3,1:3)=3其他情况,a = 1 2 3; 4 5 6a = 1 2 3 4 5 6或者可以利用其他量赋值:a = 1 2 3; b = 4 5 6; c = a; b; d = a b 另外,对于等差情况还可以X=
8、(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)=9b(:,:,1,1) = 0 0 0 0 0 0 0 0 0b(:,:,2,1) = 0 0 0 0 0 0 0 0 0b(:,:,3,1) = 0 0 0 0 0 0 0 0 0b(:,:,1,2
9、) = 0 0 0 0 0 0 0 0 0b(:,:,2,2) = 0 0 0 0 0 0 0 0 0b(:,:,3,2) = 0 0 0 0 0 0 0 0 0b(:,:,1,3) = 0 0 0 0 0 0 0 0 0b(:,:,2,3) = 0 0 0 0 0 0 0 0 0b(:,:,3,3) = 0 0 0 0 0 0 0 0 9MATLAB用这种复杂但是有效的方式显示出b的值。当然,高维数组应该尽量少用,也要合理利用。Fortran的高位数组支持的到7维,仍然是声明后使用。而在MATLAB中,a(1,1,1,1,2,2,2,2,2,2,1,2)=1 %若没有写上=1则会出现错误。的
10、时候,竟然也没有出现错误提示,大量的篇幅用来显示同样的语句a(:,:,1,1,2,2,2,2,2,2,2,2) = 0当然这只是在数组中只有很少的元素(13个)的情况下。用这么高的维数做运算明显不是明智的。这种情况下,数组应与稀疏矩阵的优化有所联系,因此MATLAB可以胜任。我也没有查到一个确切的维数的限制,但是至少知道数组大小的由内存所决定了。可以用memory查询一下: memoryMaximum possible array: 752 MB (7.890e+008 bytes) *Memory available for all arrays: 1496 MB (1.569e+009 b
11、ytes) *Memory used by MATLAB: 290 MB (3.038e+008 bytes)Physical Memory (RAM): 1908 MB (2.001e+009 bytes)* Limited by contiguous virtual address space available.* Limited by virtual address space available.一些已经有的向量的运算min max mean median %中位数std %标准差diff %相邻元素差sort %排序,而且返回索引sum prod cumsum %累计元素总和cum
12、prod %累计元素总乘积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各有各的精彩。当然,就方便而言,从我的了解来看应该还是MATLA
13、B更胜一筹。方法之多样,方式之灵活,MATLAB简直让我眼花缭乱。首先对比关于数组一些信息的获取:FortranMATLAB数组上(下)界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) 在
14、数组中,个人觉得MATLAB比Fortran最大的特色在于它的缩维操作:A(2,:)=当然,如果只置空了行或者列的某一部分时,无法缩维。缩维操作给MATLAB的编程人员留下优化内存使用的空间,方便灵活,Fortran里如果想更灵活的运用内存,则恐怕只能向链表求助。另外更下策的办法如果让Fortran做同样的事情,应该用可调大小数组通过allocate和deallocate的反复操作,而且应该还要一个足够大的中间数组才能进行。对于追求效率的Fortran来讲,这是无法想象的。而MATLAB则以这种灵活性。在避免数组使用的情况下计算相图轨线的坐标时,Fortran:program graphimp
15、licit none real time0,time1 integer,parameter:m=35000 real ,parameter :a=0.25 real ,parameter :b=1 real ,parameter :c=3 real t,gap real x,y,z real x1,y1,z1 integer :i,err=0 call cpu_time(time0) x=0; y=0; z=0.989876; open(1,file=graph.txt,form=formatted,status=replace) if(err) print*, wrong! t=30000/
16、m do i=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) call cpu_time(time1) print*, time1-time0end生成了一个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
17、;c=3; for k=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; hold on%plot3(x,y,z)end%grid ontoc;运行时间显示:Elapsed time is 8.816268 seconds.如果加上画图的时间:Elapsed time is 39.565406 seconds.远远大于Fortran。如果试图把中间生成的数据用数组记录下来,内存在运行了好久之后,溢出了。稍微集中一些比较常用的MATLAB中关于线性代数的矩阵操作的函数:det 行列式norm
18、矩阵或者向量的范数null 矩阵的核零子空间orth 正交基底rank 秩subspace 子空间的夹角trace 迹expm 矩阵指数函数funm 矩阵一般函数logm 矩阵对数函数sqrtm 矩阵开平方/ 用于解方程组chol cholesky分解choline 不完全的cholesky分解cond 条件数,测试接近奇异的程度condest 估计inv 逆矩阵lu LU分解luinc 不完全LU分解qr QR分解lscov 已知covariance的最小二乘法nnls 非负的最小二乘法对于数组和矩阵上的一些运算,MATLAB显得十分方便。在此不再详细展开。MATLAB选择“牺牲资源”“提高效率”,但是实际上对内存的频繁操作并没有带来效率上的出色,而Fortran以其严谨的逻辑与明确的规定书写提高着效率,但是带来的了编程时的繁琐。对于大型的计算,Fortran是当之无愧的第一选择。在数组的操作上,Fortran呵呵MATLAB均有十分出色的表现。MATLAB方法多。可以利用很简单的代码完成Fortran需要花很多功夫才能编出来的程序。但是MATLAB的所有元素均用数组来存储,尤其是cell数组更是奇特。Fortran则严格明确,同时又在较为丰富的矩阵操作中相当好的利用了并行计算的硬件资源。二者都是计算编程人员强有力的工具。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1