MATLAB是我們常用的工具。而快速學習和熟練掌握MATLAB對于高效完成工作很有意義。本文從親身的經(jīng)驗出發(fā),介紹一下怎樣學習和使用MATLAB,這些辦法大都是本人和同事們經(jīng)常使用且被認為不錯的辦法。
1. 學習MATLAB的基礎(chǔ)語法略過了。如果你不太確定,可以在command下邊用一些簡單的數(shù)字試一試。如果你習慣用C,那么注意要將運算矩陣化,什么叫運算矩陣化呢?就是盡量將循環(huán),尤其是帶if的循環(huán)用矩陣代替。舉個例子:比如把數(shù)組中所有大于1000的數(shù)據(jù)置為1000,而其它的數(shù)據(jù)不變,可以寫作x(x>100)=100;如果采用for循環(huán)加if來做,那么效率是它的1/4。有時候似乎必須用for解決了,比如將一個1x6的數(shù)組改成2行3列,那么不妨可以找找?guī)旌瘮?shù),此例用reshape就可以解決。如果必須要用循環(huán),且對某數(shù)組x的若干下標依次賦值,則一定要先定義x這個數(shù)組,例如可以用x=zeros(1,1000)。否則等于聲明了一個不定長度的數(shù)組,效率十分低下。這是絕大多數(shù)程序效率損失的原因,當然是有辦法進行檢查的。查的辦法是用MATLAB提供的profiler工具。位于tools->open profiler,工具欄也有圖標。在這個工具上寫入你想運行的函數(shù)名或者m文件名,程序就開始運行,運行完畢后,會將其每個語句的執(zhí)行時間統(tǒng)計出來,一下子就可以找到癥結(jié)。如果是循環(huán)體內(nèi)數(shù)組賦值類的操作,一般是不正常的,你應(yīng)該看看是否犯了沒有初始化的錯誤。有時候一些函數(shù)會占用掉很多時間,你可以想想有沒有辦法替代它們,如果沒有就進到這個函數(shù)內(nèi)部再去找一找,有時候會有優(yōu)化的空間。最后的結(jié)果往往是絕大部分時間已經(jīng)耗費在了你很清楚的地方,比如調(diào)用的底層C函數(shù)、卷積運算、矩陣運算等等。
2. 在MATLAB常用的函數(shù)中,clear,clc,figure等等要牢記。另外,有時候需要注意某些庫函數(shù)的第二個返回值,往往就是你想要的,比如max函數(shù)的第一個值時最大的數(shù)值,而第二個就是數(shù)組的角標,直接用[value index]=max(x)就可以同時獲得,如果你把第二個數(shù)丟了,再用find去找,那就累死了。
3. 學習MATLAB的toolbox函數(shù)及其用法不需要看雜七雜八的書,它的幫助足夠了。打開help->product help,左側(cè)列出了很多toolbox,每個toolbox都有幾個子項,Getting Started里邊具有最權(quán)威的上手示例,如果需要長期使用,應(yīng)該把User’s Guide看一遍,沒有多少內(nèi)容,一般一兩天時間就夠了。里邊具有很多示例的代碼,有用的部分一定親手試一下。另外對于典型應(yīng)用,它都有Examples,雖然對于前沿領(lǐng)域來講,這些算法有點“老”,但是其精煉和高效是其他教材無可比擬的。它會給你展示在這個領(lǐng)域的專家最起碼的實驗技能和討論的主題,甚至可以當做所學專業(yè)可能的實驗課本。如果你對上述過程中的具體函數(shù)及其實現(xiàn)感興趣,可以到Functions里邊找,那里對每個函數(shù)都有詳細的解釋。如果你對這個函數(shù)的實現(xiàn)很感興趣,那么直接在command中寫 “edit 函數(shù)名”,你就可以看到它的實現(xiàn)的源代碼。甚至某些圖形工具,例如fdatool、imtool、bertool等等。函數(shù)內(nèi)部有可能嵌套更深層的函數(shù),那么請你用一個你最熟悉的數(shù)據(jù)調(diào)用它,通過調(diào)試+單步跟蹤的方式一步一步查下去,由于數(shù)據(jù)你是熟悉的,因此你可以很快搞定其內(nèi)部工作方式。
有兩種例外,其一是MATLAB新的函數(shù)啟用的object類型,對其源碼進行了封裝,通過edit可能看不到什么東西,那么怎么找到它的源代碼呢?有兩個辦法,其一是單步跟蹤,如果還解決不了,那么可以用上文提到的profiler工具,它會把調(diào)用到的函數(shù)一一列寫,很有可能是最頂層的某個函數(shù)進不去,可以在其下的函數(shù)上定一個斷點,看看數(shù)據(jù)跑過來怎樣,再往下一步步跟蹤,基本上就不會有單步跟不到的地方了。
另一個例外是遇到了MATLAB的buildin函數(shù)或者C函數(shù),那就真的沒辦法了,因為這兩個函數(shù)是沒有源代碼的。
MATLAB庫函數(shù)有統(tǒng)一的結(jié)構(gòu),第一部分是幫助信息,help可以看到的部分,之后是變量檢查,最后是實現(xiàn)過程。由于很多函數(shù)為了通用,實現(xiàn)的細節(jié)不是最優(yōu)的,并且對參數(shù)做了太多的檢查,如果你需要更好的性能,可以將其關(guān)鍵的語句提煉出來,或者用純粹的矩陣運算表述出來,往往可以起到提速的作用。另外,你也可以把自己的注釋寫在最前邊,這樣就可以通過help查到。
4. 有幾個在源代碼編輯器中的快捷鍵很管用,推薦掌握,ctrl+R注釋選定代碼,ctrl+T取消注釋,調(diào)試的F5,F10,F11之類,終止運行中的程序ctrl+C。另外,如果你在源碼編輯器中閱讀源代碼時遇到一個函數(shù)想查看,直接在函數(shù)上點右鍵,選擇open selection即可。MATLAB保存之后的代碼也是可以撤銷的,甚至可以撤銷到打開MATLAB時最原始時候的狀態(tài)。因此應(yīng)該常保存,以便于防止文檔丟失。源碼中可以通過兩個百分號“%%”分割源碼,甚至只執(zhí)行一部分,十分有利于比較長的源碼。
如果在command中想調(diào)用函數(shù)或者變量,敲寫前幾個字母再按tab鍵就可以得到匹配提示。如果需要查看變量,尤其是二維的數(shù)組,可以用workspace找到它并雙擊,打開Variable Editor,這個編輯器可以和Excel互相復(fù)制粘貼,很是方便。另外,各種窗體的字體和顏色大多是可以改的,在Preferences中有fonts及其他項目,可以關(guān)注一下。最后值得一提的是plot畫出的圖像由于是矢量圖,如果數(shù)據(jù)點很多的話,復(fù)制到word中很可能會顯示卡殼或很慢,可以先拷貝到畫圖里邊,然后再貼到word,這樣就是位圖了。
5. 如果遇到了大運算量,建議不要運算結(jié)束后直接繪圖或者打印結(jié)果,而應(yīng)該采用運算和結(jié)果顯示獨立的程序架構(gòu)。運算是一個程序,計算后的結(jié)果通過save語句存儲成mat文件,再用另一個程序通過load讀取此文件,這樣的好處是可以防止結(jié)果丟失和篡改。另外,為了顯示直觀和調(diào)試的方便,可以實時的將計算的進度顯示在command中,比如:
type={'AACH' 'BSCH' 'TCH/4.8_1' };
i=3;a=1;
fprintf('Calculating Logical Channel %s using %d antennas\n',cell2mat(type(i)),a);
則可以顯示出
Calculating Logical Channel TCH/4.8_1 using 1 antennas
如果制作了日志文件,那就更好了,首先打開一個文件,寫入時間戳clock,它是個數(shù)組,代表年月日時分秒之類。
logfid=fopen('log7-26.txt','a+');
fprintf(logfid,'time ');
fprintf(logfid,'%d.',clock);
fprintf(logfid,'\n');
之后依然用fprintf來打印,只不過需要加入logfid句柄。
fprintf(logfid,'Calculating Logical Channel %s using %d antennas\n',cell2mat(type(i)),a);
最后fclose(logfid); 用以關(guān)閉日志文件,幸運的是,如果由于終止運算而沒有執(zhí)行到這個語句,大多數(shù)日志結(jié)果也是存盤了的。
如果需要運算完畢后自動關(guān)閉計算機,可以加入這么一句
!shutdown -s
嘆號代表執(zhí)行一個外部命令,后邊是windows默認的關(guān)機程序,可以在運行對話框?qū)嶒炓幌?,如果需要停止已?jīng)關(guān)機,那么再運行shutdown –a。
6. MATLAB功能實在很多,新功能層出不窮,最好使用新的版本,MATLAB不一定總是對的,很多細節(jié)是有失偏頗的,我就遇到了幾次,最嚴重的一次是gaussfir函數(shù)出來的結(jié)果整個就是不對的,后來發(fā)現(xiàn)高版本已經(jīng)修正了,因此盡量使用更高的版本。有時隨著版本更新,會對你的代碼提出新的要求,比如用1i代替j代表復(fù)數(shù),或者用strcmp而不是~=比較字符串等等,它都會用紅線提醒,你可以根據(jù)它的提示予以更正。
7. 對于是否使用Simulink,我認為它很直觀,但是缺點是效率不高(主要針對通信物理層仿真),尤其是蒙特卡洛仿真這種需要大數(shù)據(jù)量的循環(huán)仿真。當時曾經(jīng)嘗試過,學長用Simulink去做,跑5萬點就慢死了,我自己用代碼來寫,跑到50萬點比他的快很多,后來又通過提取函數(shù)內(nèi)部實現(xiàn)和矩陣優(yōu)化等方法又有了很大的提升。有時發(fā)現(xiàn)循環(huán)和判斷太多了,只能用C來做。這是MATLAB的很多庫函數(shù)的選擇,因此如果你需要更高的效率,也可以這樣來做。MATLAB-C聯(lián)合編程雖然有利于提高運算效率(甚至可以利用好多核),但是很難調(diào)試C代碼,在編寫時一定要注意緩沖區(qū)溢出之類的問題,因為它會使整個MATLAB崩潰而重啟。因此最好先在VC調(diào)試好,再跟接口連接起來。當然,調(diào)試的時候C代碼部分沒法單步,但是printf還是可以用的。另外,MATLAB的界面制作工具很好用,而且做出來的東西很贊,建議花點時間學一學,能夠操縱按鈕,讀取復(fù)選框和文本的數(shù)值基本上就夠用了,它會使你的結(jié)果匯報變得很直觀。
很抱歉,由于思路未加整理,十分凌亂,謹此獻給常常使用MATLAB的同志們,希望能夠起到一點作用,使大家能善于利用MATLAB開展自己的研究工作。