From 9469785a0bd044c332ae67b238e894920b816e74 Mon Sep 17 00:00:00 2001 From: Euler-37 Date: Sun, 31 Mar 2024 02:26:53 +0000 Subject: [PATCH] deploy: 78087e1113d4a8fa3b3b27d866840a9ad8492d2d --- 404.html | 2 +- ch01-00-getting-started.html | 2 +- ch01-01-install-compiler.html | 2 +- ch01-02-gfortran.html | 2 +- ch01-03-fpm.html | 2 +- ch02-00-first-fortran.html | 2 +- ch02-01-program-unit.html | 2 +- ch03-00-declaration.html | 2 +- ch03-01-precision.html | 2 +- ch03-02-operation.html | 2 +- ch03-03-array.html | 2 +- ch03-04-character-array.html | 2 +- ch04-00-if.html | 2 +- ch04-01-select.html | 2 +- ch04-02-do.html | 6 +- ch04-03-do-array.html | 271 ++++++++++++++++++++++++++++++++++ ch05-00-function.html | 6 +- ch05-01-subroutine.html | 2 +- ch05-02-funckeyword.html | 2 +- ch05-03-callback.html | 2 +- ch05-04-module.html | 2 +- ch05-05-overload.html | 2 +- ch06-00-file.html | 2 +- ch06-01-format.html | 2 +- ch07-00-type.html | 2 +- ch07-01-procbind.html | 2 +- ch07-02-typeoverload.html | 2 +- index.html | 2 +- mdbook-cheat-sheet.html | 2 +- preface.html | 2 +- print.html | 69 ++++++++- searchindex.js | 2 +- searchindex.json | 2 +- title-page.html | 2 +- 34 files changed, 375 insertions(+), 37 deletions(-) create mode 100644 ch04-03-do-array.html diff --git a/404.html b/404.html index e0a3cbd..84369ff 100644 --- a/404.html +++ b/404.html @@ -85,7 +85,7 @@ diff --git a/ch01-00-getting-started.html b/ch01-00-getting-started.html index 7066e30..d52929e 100644 --- a/ch01-00-getting-started.html +++ b/ch01-00-getting-started.html @@ -84,7 +84,7 @@ diff --git a/ch01-01-install-compiler.html b/ch01-01-install-compiler.html index 6b6994c..cacca91 100644 --- a/ch01-01-install-compiler.html +++ b/ch01-01-install-compiler.html @@ -84,7 +84,7 @@ diff --git a/ch01-02-gfortran.html b/ch01-02-gfortran.html index 7fb6d62..eac4c1a 100644 --- a/ch01-02-gfortran.html +++ b/ch01-02-gfortran.html @@ -84,7 +84,7 @@ diff --git a/ch01-03-fpm.html b/ch01-03-fpm.html index 7ea6d0f..779c9e1 100644 --- a/ch01-03-fpm.html +++ b/ch01-03-fpm.html @@ -84,7 +84,7 @@ diff --git a/ch02-00-first-fortran.html b/ch02-00-first-fortran.html index 69153d1..6479bb8 100644 --- a/ch02-00-first-fortran.html +++ b/ch02-00-first-fortran.html @@ -84,7 +84,7 @@ diff --git a/ch02-01-program-unit.html b/ch02-01-program-unit.html index af24265..3e13c2d 100644 --- a/ch02-01-program-unit.html +++ b/ch02-01-program-unit.html @@ -84,7 +84,7 @@ diff --git a/ch03-00-declaration.html b/ch03-00-declaration.html index 5e38a86..34eb0e5 100644 --- a/ch03-00-declaration.html +++ b/ch03-00-declaration.html @@ -84,7 +84,7 @@ diff --git a/ch03-01-precision.html b/ch03-01-precision.html index 75a825c..a8efcea 100644 --- a/ch03-01-precision.html +++ b/ch03-01-precision.html @@ -84,7 +84,7 @@ diff --git a/ch03-02-operation.html b/ch03-02-operation.html index a9d6dc2..7f56f68 100644 --- a/ch03-02-operation.html +++ b/ch03-02-operation.html @@ -84,7 +84,7 @@ diff --git a/ch03-03-array.html b/ch03-03-array.html index 5e68f37..720f8e1 100644 --- a/ch03-03-array.html +++ b/ch03-03-array.html @@ -84,7 +84,7 @@ diff --git a/ch03-04-character-array.html b/ch03-04-character-array.html index a148c9a..4b345a5 100644 --- a/ch03-04-character-array.html +++ b/ch03-04-character-array.html @@ -84,7 +84,7 @@ diff --git a/ch04-00-if.html b/ch04-00-if.html index 93c025e..0e5e7bb 100644 --- a/ch04-00-if.html +++ b/ch04-00-if.html @@ -84,7 +84,7 @@ diff --git a/ch04-01-select.html b/ch04-01-select.html index bccb648..7ea4348 100644 --- a/ch04-01-select.html +++ b/ch04-01-select.html @@ -84,7 +84,7 @@ diff --git a/ch04-02-do.html b/ch04-02-do.html index c54e409..39f962a 100644 --- a/ch04-02-do.html +++ b/ch04-02-do.html @@ -84,7 +84,7 @@ @@ -313,7 +313,7 @@

隐式循环 - @@ -327,7 +327,7 @@

隐式循环 - diff --git a/ch04-03-do-array.html b/ch04-03-do-array.html new file mode 100644 index 0000000..2d20217 --- /dev/null +++ b/ch04-03-do-array.html @@ -0,0 +1,271 @@ + + + + + + 数组与循环 - 现代Fortran程序设计 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + +
+
+

数组与循环

+

在前一节中,我们已经看到了隐式循环在数组中的应用,但是在实际的代码编写中,我们需要大量的编写多重循环。隐式循环和数组构造器的组合虽然在直觉上很方便,但是会引入临时数组,带来一定的性能损耗。

+

数组的列优先

+

前面我们已经提到了Fortran中的数组是列优先的。所谓列优先就是靠近数组左边的元素,在内存中离得更近。在我们使用多重循环的时候,对离得近的元素优先进行计算,将会带来一定的速度收益, +在计算机科学中,这种被称为访存优化。实际上,想要写出性能较高的Fortran程序,往往只需要注意数组的列优先,以及不要产生过多的临时数组

+

一个简单的关于数组列优先优化的例子是矩阵的乘法,一般的矩阵乘法大家都会写成这样

+
  do i=1,n
+    do j=1,n
+      do k=1,n
+        c(i,j)=c(i,j)+a(i,k)*b(k,j)
+      end do
+    end do
+  end do
+
+

此时我们看到,内存循环为k,只有b(k,j)满足了列优先的条件,c(i,j)a(i,k)都是i指标更靠前。所以我们可以尝试如下的优化

+
  do j=1,n
+    do k=1,n
+      do i=1,n
+        c(i,j)=c(i,j)+a(i,k)*b(k,j)
+      end do
+    end do
+  end do
+
+

我们可以尝试对比运行时间,来观察速度的变化。这里我们使用了内置的函数system_clock,第一个参数是当前时刻的时间(并不是绝对时间),第二个参数是时间的颗粒度,用两个时刻的时间 +相减,再除以颗粒度就是实际的用时(单位为s).

+
program main
+  implicit none
+  integer::i,j,k
+
+  integer,parameter::n=1000
+  real(8)::a(n,n),b(n,n),c(n,n)
+  integer(8)::tic,toc,rate
+  call random_number(a) !给数组填充随机数
+  call random_number(b)
+  call system_clock(tic,rate)
+  c=0.0_8
+  do i=1,n
+    do j=1,n
+      do k=1,n
+        c(i,j)=c(i,j)+a(i,k)*b(k,j)
+      end do
+    end do
+  end do
+  call system_clock(toc,rate)
+  write(*,*)"time(ijk)=",1.0_8*(toc-tic)/rate,"s" !注意此处为了避免整数除法,需要这样处理
+  write(*,*)"c(n,n)=",c(n,n)
+  call system_clock(tic,rate)
+  c=0.0_8
+  do j=1,n
+     do k=1,n
+        do i=1,n
+           c(i,j)=c(i,j)+a(i,k)*b(k,j)
+        end do
+     end do
+  end do
+  call system_clock(toc,rate)
+  write(*,*)"time(jki)=",1.0_8*(toc-tic)/rate,"s"
+  write(*,*)"c(n,n)=",c(n,n)
+end program main
+
+

我们使用release模式运行,release模式相对于之前的默认模式(通常是debug模式),运行速度更快

+
ime(ijk)=   1.3653479070000001      s
+ c(n,n)=   240.96782832895653
+ time(jki)=  0.16677901700000000      s
+ c(n,n)=   240.96782832895653
+
+

可以看出,两者的运行时间大概相差了8倍。所以在实际的计算中,我们需要注意数组的列优先带来的收益

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + diff --git a/ch05-00-function.html b/ch05-00-function.html index 5f439b3..7ec0625 100644 --- a/ch05-00-function.html +++ b/ch05-00-function.html @@ -84,7 +84,7 @@ @@ -241,7 +241,7 @@

函数的定