面向科研的編程技巧 Research Oriented Programming Skills

本文長期更新,彙總一些自己在平時科研中逐漸領悟到的一些編程技巧,歡迎交流,歡迎指導。文中的內容基本會結合自己遇到的具體例子來說明。
科研與做產品不同,在寫代碼的過程中往往要經過很多調試,修改參數,調整數據結構等,因此便於調試是面向科研編程的第一要義。

General:

關於 Git 的使用

我現在還沒有很熟練的應用 Git 中的分支和版本回退等功能,主要還是當作一個代碼託管和多終端查看的地方。其實在寫代碼的過程中,頻繁地 commit 是個好習慣。但注意,從遠程的 repository 拉取代碼到本地覆蓋之前還是要想清楚。另外個人覺得,本地的倉庫可以經常更新,但推送到遠程倉庫去的最好還是取得階段成果的版本。另外注意保持寫說明的好習慣。

關於代碼複用

在編寫代碼中經常出現這樣的情況,給 A 項目寫了個函數(文件),結果 B 項目中也會用到。一個辦法是把原來的函數或者文件複製一份到新的項目中去。但這樣就有一個問題,隨着後續的調試,本來功能相同或相似的代碼會生長成兩個不同的版本,這樣在後面需要合併的時候往往又會耗費大量的時間和精力。因此,比較好的方法就是在需要調用別處代碼的時候直接將別處的代碼的引用指向新的項目。
比如,在MATLAB中,可以用 addpath() 將另一個函數所在的路徑添加到當前的程序中。
另外,在 VS 和 MATLAB 聯合調試中,可以結合宏的使用共同調試一份源代碼。

關於 solver 的接口

在仿真中需要對多個 solver 進行比較時,最好分別用 wrapper 函數分別將這幾個 solver (不管是自己寫的還是調用現成的)寫成統一的接口,這樣在仿真時便於輸入,也便於對輸出進行比較。
比如,在比較幾個 QP 求解器的速度和迭代次數時,將幾個 solver 的輸入都寫成自己通用的標準 QP 命題中參數,同時將迭代次數和求解時間在 wrapper 函數中進行提取和計算,作爲接口的標準輸出,這樣在外層調用 solver 的函數時更加方便整齊。

For C Code:

關於宏的使用

剛開始接觸 C 時是不大會用宏的,但逐漸瞭解並走了很多彎路後才認識到宏的價值。一個在代碼中會經常訪問和修改的參數,我們可以用一個變量來表示。那麼代碼中經常使用和修改的語句(命令)就可以用宏來表示。
比如,我的一個 C 代碼在初步調試後要用 MEX 文件連接在 MATLAB 中進行調試。在 VS 中調試時,我可以用 printf() 來打印變量值;而在 MATLAB 中調試時,打印函數要用 mexPrintf() 。如果不用宏,我可能要手動修改源代碼中的所有 printf() 。那如果我採用宏定義:

#define Print mexPrintf     // For Matlab debug
//#define Print printf      // For Visual Studio debug

那麼即使我切換使用 VS 和 MATLAB 進行調試,也能很容易地修改源代碼中的打印函數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章