[心得] Fortran 优缺点

楼主: dryman (dryman)   2024-06-30 00:01:48
小弟最近正在研究数值算法
顺利的话,希望能将程式回馈给LAPACK
在此之前我主要进行C/C++/Python的程式设计
Fortran是我在研究数值算法的同时,顺带一起学的
我的分析以 Fortran 90 为主,并且遵循 LAPACK 设计守则
比较对象包含C/C++/Python
最大的优点,就是多维资料及寻址
real, intent(in) :: A(LDA, *)
可以轻松的使用 A(i, j) 来寻址资料
在Fortron 90 甚至可以进行向量版本的计算
例如 y(1:n) = a * x(1:n) + y(1:n)
只要加入 -mavx2 或是 -mavx512f 就能轻松编译出使用SIMD指令集的程式
https://godbolt.org/z/EPxsPsdoW
numpy 虽然也有支持 a[1:m, 1:n] 这样的寻址模式
但我们很难期待它有高效能
C/C++ 对应同样的资料结构,就必须写 A[j*lda + i],非常的不方便
一不小心弄错i, j,程式就会出错
需要多写一层循环也会影响程式的阅读性
这个独特的优点直接压过所有的缺点,使得它成为设计数值程式的首选
其语法与matlab, numpy类似
却有C/C++的速度
如果是作为数值算法的使用者,那么numpy/scipy/matlab等都是好选择
但如果是要作为数值算法的实作者,fortran的效能还是上述语言无法取代的
可惜的是Fortran让人恼人的缺点也不少
1. 无法内嵌组合语言
高效能需求的矩阵乘法函式库BLAS,效能好的都已经改用C+组合语言来撰写
毕竟编译器能提供的帮助有限,少数的地方我们还是希望能精准的控制组合语言的输出
一个算是重视效能的语言却禁止结合组合语言,我觉得其决策弊大于利
(官方说法是Fortran的设计初衷就是不绑定机器)
连rust都能使用assembly intrinsics了
对于习惯使用intrinsics来加速的我来说,这个禁令非常的绑手绑脚
2. 缺乏标准测试环境
作为软件工程师,我的开发习惯从设立一个测试环境开始
不论是测试自己对语法的熟悉度、函式库使用起来是否正确
或是一些用来验证开发中程式内部结构的程式,都非常的好用
我一开始是从fortran维基上找
https://fortranwiki.org/fortran/show/Unit+testing+frameworks
我不知道别人实测的心得如何
我自己是觉得相当难以上手
所以我早期的测试程式是帮fortran写c header file后
再以google test来进行测试
后来干脆自己开发一个与cmake结合的版本:
https://github.com/dryman/fortran_unit_test
它符合多数程式语言在写测试时的习惯
也就是一个测试就是一个function
然后测试环境会依序测试每个function是否正确执行
3. 与主流程式语言不同的语意
例如不能使用 IF (A .and. B) ,在 A 为非的时候不执行 B
(no short circuit)
不能使用 X = A ? B : C; 这种在一般CPU都有特殊的优化组语 (conditional move)
不过fortran 2023就真的可以写
value = ( a > 0.0 ? a : 0.0)
4. 与 C 的程式作连结时,字串处理的问题
在我撰写CMake/Ctest for fortran时,最让我苦恼的问题是处理字串
在 C 当中,我们使用int argc, char** argv来传递arguments
然而在fortran当中,要将char**转成fortran容易处理的资料,却相当痛苦
最简单的选项,是将其变为array of size-1 array, each contain a character
但是这样的资料却又没办法丢给其他的fortran字串处理程式
例如ctest其实支援传递parameterized arguments
./my_test test_fn 50 100
50 和 100 会被当作 5, 1
我最后的解法是把C stdlib的atoi搬进fortran来使用
这问题在fortran 2023似乎也能解决:
US 09 会增加 call c_f_strpointer
5. 变量宣告必需要在程式开头
这点也是对开发相当冗余的设计
不过看起来没有机会改善 :(
写了这么多,对缺点的抱怨多过优点
不过实际上我是真的蛮感激fortran 90的语法对开发数值程式的帮助
要在其他语言上开发相同的功能,其实更加不容易
以上就是我的心得,也欢迎对程式语言及数值程式有兴趣的朋友分享想法
作者: blc (Anemos)   2024-06-30 14:16:00
感谢心得。程式写多了我觉得宣告是优点
楼主: dryman (dryman)   2024-07-01 23:38:00
型别宣告是好事。但只能放在function最前面宣告就很卡
作者: fragmentwing (片翼碎梦)   2024-10-29 21:51:00
用python不在init就把所有变量先写出来然后=None或False就有点毛毛的*class的 init

Links booklink

Contact Us: admin [ a t ] ucptt.com