
圖片來源:unsplash.com
盡管計算(computing)在科學領域越來越重要,研究論文卻很少提供作者的基礎代碼。即便提供了,同行們(men) 也很難順利運行,一些人甚至在發了論文以後發現想重複自己曾經用過的代碼都會(hui) 遇到問題。畢竟,計算機運行環境發展迅速,編程語言也在不斷更新,如何讓多年前的古董代碼重新順利運行成了令許多程序員及科研人員頭疼的難題。
十年可重複性挑戰
為(wei) 了攻克這個(ge) 難關(guan) ,法國國家信息與(yu) 自動化研究所(French National Institute for Research in Digital Science and Technology,INRIA)的計算神經科學家兼程序員Nicolas Rougier和法國國家科學研究中心(French National Centre for Scientific Research,CNRS)的理論生物物理學家Konrad Hinsen在2019年共同構想了一個(ge) 解決(jue) 方案:“十年可重複性挑戰”(Ten years reproducibility challenge)項目。這個(ge) 挑戰項目鼓勵科學家們(men) 重現至少十年前他們(men) 發表的文章中的代碼。參與(yu) 者還需在2021年6月舉(ju) 行的研討會(hui) 上討論他們(men) 的收獲。成功的案例會(hui) 刊登在ReScienceC雜誌上。ReScienceC是Rougier和Hinsen在2015年創辦的雜誌,用來記錄研究人員重複已發表論文的代碼的情況,以此統計研究的可重複性。
Hinsen表示,這項挑戰旨在“尋找有效的編寫(xie) 和發表代碼的技巧,讓代碼十年後還能運行”。項目的啟動恰巧與(yu) 著名的Python 2退出曆史舞台在同一天——2020年1月1日。Python 2曾是科學界流行的高級編程語言,被係統支持使用超過20年。(Python 3於(yu) 2008年發行,現在還在發展中,但這兩(liang) 個(ge) 版本的差異很大,用一個(ge) 版本寫(xie) 的代碼可能無法在另一個(ge) 版本中正常運行。)畢竟,“十年在軟件世界中是一段很長很長的時間”,伊利諾伊大學厄巴納-香檳分校研究計算重複性的Victoria Stodden 表示,這項挑戰通過設立10年的標準,有效激發了研究人員去突破代碼可重複性的時間局限。
盡管項目任重道遠,還是有35個(ge) 人接受了這項挑戰。他們(men) 共提出了43篇等待檢測重複性的論文,其中28篇產(chan) 生了重複性報告。ReScienceC雜誌今年開始發表他們(men) 的工作。參與(yu) 者使用了包括C、R、Mathematica以及Pascal在內(nei) 的多種編程語言,還有一位參與(yu) 者甚至重新運行了用 SBML(Systems Biology Markup Language)編碼的分子模型。
挑戰重重
挑戰的發起人Rougier 也參與(yu) 到了項目中,他重複運行了這項挑戰中最古老的代碼:自己1歲時在蘋果電腦上寫(xie) 的用於(yu) 圖片放大的程序。這個(ge) 代碼當時被刊登在了已不複存在的法國Tremplin Micro雜誌上。32年後,Rougier已經不記得代碼和它晦澀的 AppleSoft BASIC指令是如何運行的了。不過他還是在網上找到了當年的代碼並在網頁版的蘋果II模擬器上跑了一遍。
然而,難點在於(yu) 讓它在真正的蘋果II電腦上順利運行。硬件不是問題,Rougier 辦公室有一台蘋果II電腦。但由於(yu) 蘋果II電腦誕生的年代還沒有USB數據線和互聯網,現代電腦又無法連接老式磁盤驅動器,Rougier不得不用定製硬件(custom hardware)和老式軟盤(vintage floppies)來幫助電腦加載代碼。如同考古挖掘一樣,雖然過程曲折,但Rougier還是讓 30 多年前的代碼得以重見天日。
然而,另一位發起人Hinsen就沒那麽(me) 幸運了。在上個(ge) 世紀90年代,Hinsen習(xi) 慣於(yu) 把自己的代碼儲(chu) 存在磁帶上。然而現在,雖然磁帶還在,它的閱讀器卻已經絕版了,Hinsen的代碼隻能被封在磁帶中了。
跟不上時代的運行環境
除了硬件,過時的電腦運行環境也給參與(yu) 者帶來了不少困擾。意大利的計算物理學家Sabino Maggi在1996年曾用Fortran語言來為(wei) 一個(ge) 被稱為(wei) 約瑟夫結的超導裝置建模,並用微軟的Visual Basic語言處理結果。Fortran語言這麽(me) 多年倒是沒什麽(me) 變化,可Visual Basic已經絕版了,無法在現有的Windows 係統上運行(現在替代它的是Visual Basic.NET,二者隻有名字看起來還有點聯係)。為(wei) 了運行代碼,他不得不在Mac電腦上安裝了十多年前Windows 係統的模擬機,再在模擬機上安裝1994年左右發行的微軟DOS 6.22和Windows 3.11,以及他在網上找的Visual Basic安裝盤。

二十世紀九十年代初期的Win3.11操作係統界麵
Maggi承認在模擬機上安裝這些在使用、修改上有限製的專(zhuan) 有軟件存在合法性問題。不過他最早在進行研究時曾有這些工具的有效使用許可證,這使他覺得自己“至少從(cong) 道義(yi) 上”有權使用軟件。
然而,問題還沒有解決(jue) 。Maggi 不知道自己該使用哪個(ge) 版本的Visual Basic語言。微軟發行的多個(ge) 版本的語言往往與(yu) 前一個(ge) 版本不兼容。Maggi已經記不清自己1996年用的是哪個(ge) 版本的編程語言了。更糟糕的是,他當年記錄這些細節的筆記本也由於(yu) 一次地下室漏水被銷毀了。因此,Maggi不得不耗費巨大的精力重寫(xie) 當年的代碼。

圖片來源:Sabino Maggi | Nature
無獨有偶,INRIA的研發工程師Ludovic Courtès在重新運行2006年用C語言寫(xie) 的對比不同數據安裝策略的代碼時遇到了麻煩。受程序員青睞的應用程序編程接口(Application Programming Interface,API)可以將兩(liang) 個(ge) 不同的軟件對接,方便程序員調用其它軟件的功能、打通軟件間的數據;而操作係統等運行環境的改變會(hui) 導致API的變動。API的變動使他的代碼無法用當前的軟件庫壓縮。他隻好將多個(ge) 電腦組件改回到舊版本。Courtès表示電腦係統的發展如同《愛麗(li) 絲(si) 漫遊奇境記》中的兔子洞,裏麵會(hui) 發生什麽(me) 都是未知的。
解決(jue) 策略
現在,為(wei) 應對變化未知的運行環境,研究人員可以用Docker容器和Conda虛擬環境來對電腦運算環境進行打包備用。Conda是一個(ge) 開源通用包管理係統兼環境管理係統,可以安裝多版本的軟件包及其依賴軟件,並在它們(men) 之間輕鬆切換。不過,有好幾位參與(yu) 者都選擇了另一個(ge) 辦法:Linux通用包管理係統Guix。Guix的好處在於(yu) ,它具備了科研論文可重複性的黃金準則:環境的全麵可重複性,以及透明的代碼版本。
此外,為(wei) 了提高長期可重複性,為(wei) 代碼存檔尤為(wei) 重要。INRIA的計算機科學家Roberto DiCosmo曾試圖在自己和合作者的多個(ge) 備份硬盤裏尋找1998年平行編程係統OcamlP3l的代碼,卻怎麽(me) 也找不到。毫無辦法的他隻好在他2015年建立的Software Heritage網站上進行搜索。考慮到Software Heritage在他開發OcamlP3l時還不存在,DiCosmo 並沒有抱太大的希望。然而神奇的是,他居然搜到了 OcamlP3l 的源代碼!原來,Software Heritage 通過定期抓取 GitHub 等代碼共享站點的信息,收集存放了大量計算機程序的源代碼。就像因特網為(wei) 網頁存檔那樣,Software Heritage 為(wei) 軟件源代碼進行存檔。
雖然不少參與(yu) 者發現,當年能順利運行的代碼現在頻頻報錯;但也有輕鬆化解問題的大佬。CNRS 的生物物理化學家 Charles Robert 就是其中一位。1995 年,他曾在筆記本軟件上運行 Mathematica 來為(wei) 真核生物染色體(ti) 的 3D 結構建模。當年在運行時,Robert 的代碼出現了結構缺陷以及代碼片段順序混亂(luan) 等來自筆記本軟件的問題。如今,再次麵對當年的代碼,他通過將代碼分解成模塊進行測試避開了這些問題。他還利用版本控製(是指對軟件開發過程中各種程序代碼、配置文件及說明文檔等文件變更的管理,是軟件配置管理的核心思想之一)的方法來追蹤代碼的變更,記錄每個(ge) 版本的軟件運行的結果。
DiCosmo和Robert的例子或許可以給致力於(yu) 提高代碼長期可重複性的研究者們(men) 一些啟示。雖然難以保證多年前的古董代碼一定能再次運行,但還是可以在平時編寫(xie) 代碼時采取有效的策略來增加成功的可能性。具體(ti) 策略如下:
編碼(Code):將計算和數據處理包含在代碼中。不要使用基於(yu) Excel等點擊界麵的流程圖。
存檔(Document):利用記事本等軟件詳細解釋代碼運行過程,定義(yi) 預期的參數和需要的運算環境。
記錄(Record):記錄重要參數,例如遞歸程序開始時使用的種子值(seed value)。
測試(Test):創建一套測試功能。利用陽性陰性對照數據集來確保你得到想要的結果。邊開發代碼邊進行測試,及時處理bug。
建立指南(Guide):創建一個(ge) 主腳本(如“run.sh”文件)用來下載所需的數據集和變量,執行工作流程並提供明顯的代碼入口點(entry point to code)。
建檔案(Archive):GitHub是流行的非永久性代碼線上存放處。Zenodo,Figshare和Software Heritage可以長期穩定存放代碼。
追蹤(Track):利用Git等版本控製工具記錄你的項目曆程。標注每個(ge) 結果對應的版本。
打包(Package):利用容器工具(Docker,Singularity)、網頁服務器(Code Ocean, Gigantum, Binder)或虛擬環境管理器(Conda)創建隨時可用的運行環境。
自動化(Automate):利用持續集成服務(Travis CI等)將項目進行持續性自動化測試以控製代碼質量。
簡化(Simplify):避免使用難安裝的第三方代碼庫。
核對(Verify):檢查代碼在不同運行環境的可移植性。
無論選擇哪種方法,“十年可重複性挑戰”的參與(yu) 者們(men) 想實現代碼的重新運行仍有較大的難度。不過,他們(men) 將會(hui) 為(wei) 論文代碼長期可重複性的提高帶來許多啟示。正如英國曼徹斯特大學計算機科學家Carole Goble所說,可重複性有一定範圍,“軟件是個(ge) 不斷更新的活物,它終將凋亡;人們(men) 需要修複它或者替換掉它”。
作者:Jeffrey M. Perkel
翻譯:王千玥
編輯:魏瀟
引進來源:Nature
引進鏈接:https://www.nature.com/articles/d41586-020-02462-7
關(guan) 注【深圳科普】微信公眾(zhong) 號,在對話框:
回複【最新活動】,了解近期科普活動
回複【科普行】,了解最新深圳科普行活動
回複【研學營】,了解最新科普研學營
回複【科普課堂】,了解最新科普課堂
回複【科普書(shu) 籍】,了解最新科普書(shu) 籍
回複【團體(ti) 定製】,了解最新團體(ti) 定製活動
回複【科普基地】,了解深圳科普基地詳情
回複【觀鳥星空体育官网入口网站】,學習(xi) 觀鳥相關(guan) 科普星空体育官网入口网站
回複【博物學院】,了解更多博物學院活動詳情

