理論化學編程中的Fortran與C++之爭

來源:emuch.net/html/201111/3885537.html


理論化學編程中的Fortran與C++之爭
自從有了程序設計語言,“哪種編程語言好”就成爲了亙古不變的話題。這個問題一經提出,必然會招來一場巨大的口水仗。作者曾經在一些論壇上提出了類似 “Fortran和C++那個用的多”之類的問題,回帖全部達幾十個以上,各種意見針鋒相對,猶如Fortran和C++信徒之間的“聖戰”一般好看。
有很多人曾經請C++語言之父Bjarne Stroustrup做一個C++與其它編程語言的比較,而Stroustrup明確的拒絕了。他指出,從技術上講,一個所謂的“公平”的比較將會涉及到 大量的技術,這是一個工作量巨大的任務,絕對不是簡單的用C++和其它語言寫同一段代碼然後比較其運行時間就能完成的。這種比較涉及到具體的應用領域和用 戶需求,所處理的信息類型,編譯器的質量(不同語言的編譯器開發的投入是有相當大差別的),程序員的水平與“偏好”,編程語言的標準(如究竟是C++97 與Fortran90比較,還是應該C++0x與Fortran2003比較?)等等。他甚至認爲,這種比較是“rarely meaningful”的。
因此,今天作者也不打算爲某種編程語言搖旗吶喊,而是僅就科學計算編程領域,特別是,限於作者專業即量子化學和分子模擬,來談一談兩大“主流”編程語言:Fortran和C++的在理論化學界的應用歷史,以及某些人(包括作者)對它們的看法。
1 Fortran的美好時代
毋庸置疑,1957年出現的Fortran是世界上第一個高級編程語言。它的出現,大大降低了普通科研人員學習編程的門檻,而且增強了代碼的可移植性。在 此之前,人們都是用機器語言直接書寫程序,這種語言對於一般人而言難度太大了,而且是與運行機器相關,因此很難寫出高效且具有可移植性的程序。
例如,Roothaan在研究原子自洽場的計算時專門爲IBM 7030數字計算機寫了一些程序,這些程序用來優化Slater基組已經10多年了。不幸的是,由於該程序是完全使用IBM的機器語言所書寫,因此在20 世紀60年代,當這種機器逐漸消失時,這些程序逐漸成爲了廢品。意識到這個資源的重要性,Clementi及其同事決定把這些程序用Fortran全部重 寫,並且增加了處理Gauss基組的功能。這段代碼從此復活,成爲了量子化學程序庫中一個重要部分。
Fortran語言的重要性從此被理論化學家所知。它的優點幾乎數不勝數。首先,它的語法簡單,任何一個理論化學的研究生幾乎一天就能學會,可以迅速用它 開展工作;其次,它的運行效率極高,不要說現代編譯器(如GNU Fortran或intel Fortran編譯器),就是世界上第一個Fortran編譯器都可以將其每一語句都翻譯成幾乎沒有冗餘的、效率至少不低於手寫的機器碼;第 三,Fortran代碼具有可移植性,與機器無關。很快,在20世紀60~80年代,一批批量子化學程序如雨後春筍般出現,如早期的 Gaussian,Polyatom,以及後來的GAMESS,NWChem等等,幾乎全部都是由Fortran77編寫的。Fortran77在量子化 學領域絕對是功不可沒,它爲普及和發展量子化學做出了巨大的貢獻。那個時代,Fortran77是很多自然科學研究生的必修課。
自此,Fortran成爲了數值計算領域的“主流”語言。
2 C語言的崛起
20實際70年代,C語言逐漸崛起。這個語言是爲了編寫Unix操作系統而開發的。很快,這種“半彙編”性質的高級語言,由於其具有極其靈活的控制機器的 能力而深受計算機專業人士的喜愛。不過,由於其學習難度較之Fortran稍高,而量子化學以純粹數值計算爲主,Fortran足以滿足要求,因此C在量 子化學領域沒有什麼明顯優勢,因此大多數量子化學家對其不感興趣。此時,C和Fortran處於“井水不犯河水”的狀態。
而80年代左右,分子模擬科學開始發展。由於分子模擬的流程相對複雜,Fortran77語言在實現某些功能時稍顯繁瑣,如對某些配置文件進行語法分析, 一些模式識別和人工智能過程等等,此時C語言的優勢開始顯露,大量分子模擬領域的研究組開始用C開發程序,如分子對接軟件Autodock等等。 Fortran壟斷地位的打破,表明理論化學領域編程語言之戰的種子已經悄然的埋下。
3 理論化學軟件開發的瓶頸
在任何軟件開發領域(學術界還是商業界),前人留下的代碼庫都是無比寶貴的財富。因爲無論程序員的水平有多高,代碼畢竟是一個字一個字的敲進去的。比如矩 陣乘法這種通用的操作都需要每次重新寫,那會浪費大量寶貴的人力財力。在前人的基礎上開發新的功能,是大型軟件開發的通用規則。量子化學自60年代以來, 積累了大量的Fortran程序庫,它們的開發都是非常艱苦的,是無數量子化學家智慧的結晶,每個研究組都要在前人的基礎上繼續的研究,例如現在的 Gaussian09裏面還使用着當年Pople親手敲進去的代碼。
不幸的是,到了90年代,這種長期的積累,既是這個組的財富,同時卻也是軟件繼續發展的一個致命的阻礙。這些開發於60年代的量子化學程序,幾乎都是“無 組織無紀律”的開發的,根本沒有料到後來的發展程度。因此,很多組逐年積累達萬行的程序,幾乎毫無任何代碼美感可言:變量命名難以理解(我見過一個 Ewald求和程序裏面充斥着p,pp,ppp這樣的變量名),邏輯結構雜亂無章(goto,if之類隨意嵌套)。維護人員在閱讀以前的源碼時需要消耗大 量的精力,而這是一個痛苦的過程。早期的量子化學程序都有大量的common塊,而每個subroutine有大量的參數傳遞(有個軟件的 subroutine居然有100多個參數!!)。閱讀這種代碼簡直讓人崩潰!
插個笑話,這是一段Fortran代碼的註釋:
C 1967-Nov-11  Only the God and I know what it intends to do.
C 1967-Nov-13  Only the God knows what it intends to do.
而最大的問題是,由於程序最初的設計沒有任何軟件工程的考慮,要繼續開發和改進這種沒有封裝和可擴展性的代碼將會變得異常困難。舉一個例子。開發相對論量 子化學軟件DIRAC時涉及到了一個四元矩陣,這種四元矩陣有兩種存儲方式:A(N, N, 4)和A(4, N, N)。由於某些歷史原因,最初的設計採用了A(N, N, 4)。現在,由於內存硬件的改變,A(N, N, 4)的乘法操作比A(4, N, N)要慢4倍。但是,由於最初設計的缺陷,幾乎所有的subroutine都是顯式的處理A的各個下標,因此,若要改進A的存儲方式幾乎要對所有的代碼進 行大手術,這簡直就是不可能的任務。因此,直到現在(2011),DIRAC還在忍受着這種四倍的性能懲罰!這是不重視軟件工程的一個慘痛教訓。
由於學術領域的特性,一個組常常是“鐵打的營盤流水的兵”,一個學生參與軟件開發往往最多四五年就會離開,新來的學生要從頭學起。由於學生基本不具有軟件 工程的背景,而寫代碼水平又參差不齊,導致不同時期加入程序的代碼,不論風格還是性能都相差甚遠,這種差異更使得軟件的發展走向死衚衕。
Fortran的結構化特性是把雙刃劍。它使得程序開發的入門變得非常容易,但又使長期維護變得異常困難。特別是代碼達到萬行級別以上時候,後續開發者的工作量越來越大。此時,軟件開發者逐漸開始反思過去的教訓。新的概念:封裝,多態,面向對象開始走入他們的視野。
4後起之秀:C++
C++作爲一種混血語言,兼具面向過程和麪向對象的特性,很快穩坐了大型商業軟件開發語言的霸主地位(Not mention Java here)。但是,不知爲什麼,理論化學界的會Fortran的人往往對C++有一種說不清楚的“敵視”的態度。也許是一種情節吧,畢竟用Fortran 人們開發了很多經典的程序,就像Visual C++出現之初,很多人還在戀戀不捨的使用着Turbo C++,因爲Turbo C++開發了無數經典的軟件。
在90年代末,一些理論化學研究組終於決定放棄Fortran,這個決定應該來說是很需要勇氣的,因爲意味着放棄前人寶貴的Fortran程序庫。(注 意,這並不是說C,C++不能調用Fortran的函數或過程。但是,對於大型程序,如果這些東西不是專門設計的,混合調用會帶來很多麻煩)。Frank Neese在開發ORCA(一個量子化學程序)時毅然決定使用C++,因爲他認爲保持代碼的結構性和統一性與程序運行的性能是同等重要的。十幾年過去 了,ORCA的代碼已達百萬行,他發現C++爲保持代碼的可維護性做出了重要的貢獻。每一個新進入組的學生在一到兩週內就可以對程序作出實質性的貢獻。他 提到,新進入組的某些人確實對C++和C抱有極大的敵意,但是經過一段時間後,他們都同意“It is much more convenient to use the ORCA C++ infrastructure compared to the Fortran codes they were used to.”
不過,他也說,Fortran也可以做到這一點。但是,Fortran的面向對象特性是在Fortran90後才加入的(如module,但有人認爲這簡 直是個“ugly hack”),而歷史上大多數量子化學程序都是Fortran77的,設計本身又沒考慮軟件工程這一點,因此Fortran的面向對象特性很少直接的投入 應用。
90年代中期,分子動力學軟件NAMD開始開發。其設計者也決定採用C++。開發者之一Andrew Dalke稱,他們選擇C++的原因是爲了處理複雜的空間分解數據結構和進程間通信。NAMD是目前爲止軟件工程做的最好的科學軟件之一。直到現 在,NAMD還在維護和開發中,其性能和可擴展性在同類軟件中都是一流的。
Gaussian是用Fortran77編寫的,而90年代中期,從Gaussian公司中跑出來的一批人(Pople(我心中的神啊)和Head-Gordan)在編寫Q-Chem時,也採用了C++ ……
5 大論戰:Fortran和C++孰優孰劣
好吧,終於還是到了這個讓人頭痛的問題。
首先,我們還是看看性能吧。
一些軟件工程專業人士說,代碼的“可維護性”遠比“性能”更重要。作者認爲,在科學計算領域,這個說法是不合適的,至少換成“代碼的可讀性與性能同等重 要”,因爲這些軟件,一旦運行起來常常都是以天爲單位,其存儲讀取和浮點數操作及其巨大,一個小小的性能提升可以使運行時間縮短几天,這對提高科研效率是 及其重要的。因此,這裏將性能的考慮放在第一位。
大家都比較公認,Fortran和C在性能上沒有實質差別,因爲他們的相對底層性,每一條語句都可以比較直接的翻譯成對應的機器語言。因此決定性能的因素 幾乎只有算法。而C++則不同,C++爲了實現多態等特性,添加了大量額外代碼,這些性質可能會對性能造成損害。最爲人詬病的,就是虛函數和大型對象的復 制。例如,某軟件涉及到大量頻繁的I/O操作(例如量子化學中分子積分的緩存文件),測試發現,使用C++標準庫iostream的cout對象類要比C 的fprintf函數和Fortran的write語句要慢三倍左右。
也有人認爲,這些所謂的“性能殺手”的責任不在語言,而在程序員。例如,大循環體內的虛函數會大大降低程序的性能,而這完全可以通過重新設計類的層次結構 或使用內聯函數來解決(事實上有人認爲在理論化學程序的設計中虛函數根本就沒有必要使用);大型對象的複製可以通過預取緩存的技術來解決,或者乾脆避免這 種操作。當然,這有偷換概念之嫌。除此之外,一般認爲對於同樣的算法,Fortran,C,C++的性能沒有實質性的差異。
數值計算的經典名著Numerical Recipe,在第一版時,裏面的程序都是用Fortran(也有Lisp,Pascal之類)寫的,而2007年第三版時,所有的程序都改成了C++, 裏面也用了模板,繼承等技術,可見他們也認爲C++和Fortran的性能不會有明顯差別。
但是,還有一個不可忽略的因素,就是編譯器!像C++這樣的大衆語言,新技術廠商會爲其投入巨資進行研究,而Fortran這種現在小衆的語言,他們的開 發受到冷落。一旦編譯器的質量下降,這種語言的性能和應用也會遭到致命的打擊。一個分子模擬軟件MODELLER是用Fortran95寫的,在編譯軟件 時,無論是intel還是GNU Fortran編譯器都會產生各種各樣的錯誤,開發人員不得不禁用一些優化選項來避免這些錯誤。另一個體現是,直到現在(2011),幾乎沒有哪個廠商生 產了完全支持Fortran2003標準的編譯器!如果這樣下去,Fortran在性能上的優勢也可能逐漸消失。
下面我們看看軟件工程上的考慮。
Vincent Leroux稱,他確實發現“maintaining large Fortran projects may turn into a nightmare easily”,C++在清晰的表達抽象數據關係上有明顯的優勢。他以分子動力學軟件CHARMM和NAMD爲例,前者是Fortran寫的,後者是 C++寫的,這兩者代碼的清晰程度幾乎有天地之別。前面提到的ORCA也是一例。因此,人們傾向於認爲C++開發的程序更具有長遠的生命力,更易擴展和維 護。
當然,用Fortran寫出好的代碼也並非不可能。一個例子是分子動力學軟件TINKER,另一個就是量子化學軟件GAMESS。GAMESS已逾二十餘 年,它使用Fortran77編寫。由於它的開發非常規範(含有程序員手冊;代碼寫作堅持統一風格;代碼註釋詳細等),並具有統一的DDI接口,因此 GAMESS始終得到了量子化學界的廣泛擁護。直到現在,很多新的電子結構方法都藉助GAMESS的平臺來發展,如XMVB,XIAN CI(這兩個都是國人開發的:分別由廈大的吳瑋組和西北的文振翼組開發),SAPT等等。但是,這兩個似乎只是特例。大多數組裏Fortran的程序人們 之所以還在改進,似乎更多是出於成本的緣故。畢竟組裏累計了多年的程序是捨不得扔的,而重寫代碼所需的工作量太巨大了,或者說,根本不會做。這一點常被人 忽略,但卻很實在。比如,作者學校某個化學組至今(2011)還在使用一個用QBASIC寫的磁性計算程序,這並不是因爲他們對當初寫這段代碼的師兄懷有 感情,而是因爲:現在組裏根本沒有人會寫代碼。
6 迎合新技術?
Fortran在某些方面確實有些不思進取。從77到95標準整整經歷了19年,指針、動態內存分配、模塊技術才姍姍來遲,而迄今類似於“析構函數”的東 西也不存在,從而使垃圾回收變得非常麻煩,這對大型程序的開發十分不利。而C++不僅天然存在這些特性,其豐富的STL可以很容易的構造高層次的數據結構 (堆棧,鏈表等)。在這一方面,Fortran是應當受到批評的。
儘管並行技術,如OpenMP,MPI等同時支持Fortran和C(so C++),但是這些技術都是在90年代出現的。事實上,對於大型程序的並行很多人還是提倡使用C++。C++的抽象技術可以減少節點通信模塊與純粹數值計 算模塊之間的耦合,而Fortran很難做到這一點。就連以Fortran77爲標準的GAMESS的數據接口程序DDI也是用C寫的。前面提 到,NAMD的作者也是這麼認爲的。
2005年左右開始流行的CUDA加速技術大大提高了理論化學的計算效率,它只支持C。Fortran的CUDA技術還有些問題(Porland Group Fortran),不知何年才能見到正式版本。Terachem作爲第一個支持GPU加速的量子化學軟件,就是使用C編寫的。如果Fortran不能充分 發揮新技術的威力,它的淘汰是遲早的事,儘管作者也不願看到。
討論了這麼多,可能有讀者覺得作者已經違背了開頭提到的“不打算爲某種編程語言搖旗吶喊”的原則,有些“貶Fortran褒C++”之嫌。也許是吧。作者 本人也是Fortran的粉絲,但是在這幾年的編程中,確實感覺到在數值計算領域,Fortran已經不可能再實現壟斷地位。也許,我們確實應該接受一下 新生事物,儘管C++的語法不友好(在懂Fortran的人看來),但是還是應當嘗試一下。如果在實際的工作中,C++真的勝過了Fortran,那麼, 我們就應該接受這個事實。畢竟科技在進步,也許過幾年,我們會在地鐵上拿着iPhone來運行量子化學軟件。
見The Design and Evolution of C++前言
B Roos, C Slatez, A. Veillard, E Clementi. Technical Report RJ 518 (IBM Research, San Jose, Aug 12, 1968)
U. Ekström, University of Olso,通信
Frank Neese, Max-Planck Institut für Bioanorganische Chemie, Germany,通信
Andrew Dalke, Dalke Scientific,通信
Ben Webb, University of California San Francisco,通信
Vincent Leroux, Centre National De La Recherche Scientifique,通信
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章