[心得] 在FORTRAN呼叫MATLAB的函數(64位元)

看板Fortran作者 (挨)時間13年前 (2011/05/14 22:20), 編輯推噓9(905)
留言14則, 11人參與, 最新討論串1/1
前言:(都是廢話~可以跳過XD) MATLAB提供了向外窗口給C語言及FORTRAN語言,使得這兩種語言可以直接調動MATLAB的函 數來使用,C/MATLAB混編的教學很多,但關於FORTRAN/MATLAB,台灣用FORTRAN的本來就 少,而專精FORTRAN的人也有他們自己的一套系統,譬如TecPlot以及很多免費的FORTRAN 繪圖函數庫,所以其實真正有教怎麼用FORTRAN呼叫MATLAB函數的中文教學很少,尤其是 針對不同編譯器的設定上,最常找到的教學是CVF編譯32位元程式的設定,而IVF幾乎沒有 中文的,英文的又閱讀的很辛苦。MATLAB雖然有內建FORTRAN呼叫MATLAB的範例程式碼, 但是那是使用FORTRAN77寫成的。 也許很懂程式設計的人不用什麼教學就知道該怎麼設定,但是我想還是有很多研究生跟 我一樣上研究所才開始學程式,所以除了會寫CODE外,很多關於編譯器方面該怎麼設定也 都一知半解,尤其現在IVF跟經典教科書使用的CVF已經長得不太一樣了,所以我終於成功 能夠在FORTRAN程式呼叫MATLAB的一些函數後,想說放到網路上讓有需要使用到MATLAB及 FORTRAN的苦命菸酒生們參考如何設定。 其實大部分都是網路上東蒐集一點西蒐集一點最後整理出來的東西,而我主要是針對如何 設定及一些該注意的地方來分享,至於詳細的語法,我想有空再說吧,而且語法方面其實 都是由MATLAB提供的,所以可以參考C怎麼呼叫MATLAB函數。或是GOOGLE '調用MATLAB計 算引擎',也可以找到關於語法上的介紹。 編譯一個有呼叫到MATLAB的FORTRAN原始碼有兩種方法: (MATLAB跟FORTRAN編譯器都必須安裝) 1.使用MATLAB編譯,這個最簡單,幾乎不用設定,但是MATLAB只能懂FIX格式(77)的 FORTRAN,要讀FREE格式的,必須要在某個.bat檔裡面去修改,在此不去說明,因為 我想應該也沒人用FORTRAN寫了一個程式後還特地使用MATLAB編譯吧... (這方法需要MATLAB能辨別出使用的FORTRAN編譯器,但似乎MATLAB只認識CVF跟IVF, 其他如PGI等等其他廠牌編譯器他都不認得) 2.使用FORTRAN的編譯器去編譯,我想菸酒生們大部分應該都是使用WINDOW系統,所以下 面講的也是這個方法。會用LINUX的人都是專業的,我想應該他們都會這些了~囧 3.把MATLAB的函式庫編譯成.dll,不過這太專業了,實際上怎麼做我也不懂,我只知道 這方法可以讓程式在沒安裝MATLAB的電腦上執行。 正文: 首先是我的操作環境,我想如果操作環境不同,可能也會有些不同,所以有可以依照操 作環境不同來調整設定方式: 作業系統:Windows 7 64位元 MATLAB版本:R2010a 64位元 安裝路徑C:\Program Files\MATLAB\R2010a FORTRAN編譯器:Intel Visual Fortran 11 使用IDE介面 IDE介面是用Microsoft Visual Studio 2008 編譯組態: Debug x64 前置作業: 1.設定Win7環境變數: 控制台->系統及安全性->系統->進階系統設定->環境變數 出現的頁面會有上下兩大區塊,在下方的系統變數區塊中的變數欄尋找PATH這 項,點選後按下方的編輯鈕,在變數值那欄應該已經有很多路徑了,在最後加 上";",然後再加上下面這個路徑 C:\Program Files\MATLAB\R2010a\bin\win64 一直按確定關掉所有頁面後,重新開機(一定要重新開機!) (若程式可以編譯,但執行時卻會出現找不到XXX.dll,通常都這步驟的問題) 2.設置專案屬性: 開啟會使用到MATLAB計算引擎的FORTRAN專案,記得組態要改成x64,至於是 Debug或Release我想都沒差。 (若組態是win32,我不確定能不能呼叫64位元的MATLAB) a.專案->屬性->FORTRAN->GENERAL,在Additional Include Directories那欄 填上C:\Program Files\MATLAB\R2010a\extern\include b.專案->屬性->FORTRAN->PREPROCESSOR,在Preprocess Source Files那欄 選擇YES (這步驟重要~我卡很久後才知道要做這步驟) c.專案->屬性->LINKER->GENERAL,在Additional Library Directories那欄 填上C:\Program Files\MATLAB\R2010a\extern\lib\win64\microsoft d.專案->屬性->LINKER->INPUT,在Additional Dependencies那一欄填上 libmx.lib libmat.lib libeng.lib 確定,關掉屬性視窗。 (對於a、c、d若是不想針對特定專案,而是所有專案都可以呼叫MATLAB,可從 工具->選項裡去設定,請自行找編譯器教學......) 3.在程式碼最開頭加上 #INCLUDE "fintrf.h" 4.接著就可以用MATLAB針對FORTRAN呼叫MATLAB計算引擎的一些特定函數來寫程 式,跟在C裡呼叫的方式差不多,我個人是覺得必須要有指標的觀念才行,才 比較好懂跟自行運用。 因為這篇主要是針對64位元作業系統及64位元程式的設定及需要注意的事項 ,所以關於語法請自行參考MATLAB的說明。 以一個在FORTRAN程式呼叫MATLAB畫圖的程式碼為例,前面數字為行號: (若要把行號也寫進程式碼的話,記得#INCLUDE "fintrf.h"這行不能加行號) #INCLUDE "fintrf.h" 1 PROGRAM main 2 IMPLICIT NONE 3 INTEGER*8,EXTERNAL:: engOpen,engClose,mxCreateDoubleMatrix 4 INTEGER*8,EXTERNAL:: mxGetPr,engPutVariable,engEvalString 5 INTEGER*8::ep,T,status 6 INTEGER*8::i,j,k 7 REAL*8::nodes(2,400) 8 DO i=1,400 9 nodes(1,i)=2d0*3.1415926/400d0*DBLE(i) 10 ENDDO 11 CALL RANDOM_SEED() 12 CALL RANDOM_NUMBER( nodes(2,:) ) 13 nodes(2,:)=nodes(2,:)*2d0-1d0 14 i=2 15 j=400 16 k=0 17 ep=engOpen(' ') 18 T=mxCreateDoubleMatrix(i,j,k) 19 CALL mxCopyReal8toPtr(nodes,mxGetPr(T),2*400) 20 status=engPutVariable(ep,'voronoi_nodes',T) 21 status=engEvalString(ep,'for i=1:1:400, & plot(voronoi_nodes(1,i),voronoi_nodes(2,i),''*''); & hold on; & end') 22 status=engEvalString(ep,'axis equal') 23 status=engEvalString(ep,'axis([0,2*3.1415926,-1.1,1.1])') 24 CALL mxDestroyArray(T) 25 PAUSE '按任意鍵結束' 26 status = engClose(ep) 27 END PROGRAM main 如果程式碼正確執行,應該會出現一張用MATLAB畫的圖,上面很多*號.... 如圖http://ppt.cc/Jbsq 注意: 1.在64位元下,MATLAB的整數是8 bytes的資料型態,所以第3、4、5行可以看到 他們被宣告成8 bytes整數,第3、4行是呼叫MATLAB以及與MATLAB做資料交換 要用到的MATLAB引擎函數,簡單說就是FORTRAN與MATLAB溝通的橋樑,功能請自 行參考MATLAB的HELP,而第5行雖然不是宣告成指標變數,但其實它們的功用很 類似於指標。 2.(這點是我自己猜測的) 有些MATLAB的引擎函數是類似於傳址型態,而不能傳 值,所以像第18行的T=mxCreateDoubleMatrix(i,j,k),功能是在記憶體中 ALLOCATE一塊空間用來存放2*400的陣列,而k=0則表示此陣列都是純實數。 理論上應該寫成T=mxCreateDoubleMatrix(2,400,0)也可以(一些C語言的範例 好像也是這樣寫),但實際上會發現無法ALLOCATE,無法ALLOCATE時T會回傳0 ,所以要先令i=2,j=400,k=0,然後寫成T=mxCreateDoubleMatrix(i,j,k)才 能ALLOCATE成功。原因只是我自己的猜測,真正的原因我也不清楚。總之遇到 這種MATLAB引擎指令可用回傳的值為多少來判斷是否執行成功,若執行成功, 回傳的為一個非0值,因為回傳的是類似於記憶體位置的資料(指標),若執行 失敗,會回傳0,可以依此點來判斷MATLAB引擎指令有沒有成功被執行。 3.為了避免混亂,所以我沒加上判斷MATLAB指令是否成功執行的語句。 4.有時候雖然成功執行指令,但其實只是說成功把東西從FORTRAN傳送到MATLAB ,而MATLAB那邊若是語法錯誤,FORTRAN這邊卻不會知道(不像直接操作 MATLAB時,若語法錯誤會出現錯誤訊息),所以跑出來的結果不一定會正確。 以上,以後畫圖就不用再另外輸出數據,然後再打開MATLAB讀入數據來畫了 除了畫圖外,我想MATLAB還有很多東西可以被FORTRAN拿來使用 像我研究這個也不是因為要畫圖,其實我是要使用MATLAB內建的建Delaunay三角形的函數 因為FORTRAN的建Delaunay三角形程式碼都是外國人寫的,使用教學都英文,根本看不懂 怎麼用,所以我才會把主意打到MATLAB上。我想有些人應該跟我一樣,雖然FORTRAN資源 豐富,但是卻因為看不懂英文所以不會使用=..= 我不是專門玩程式的人,只是因為研究所需要才開始學寫程式 所以如果有什麼東西是本來就該知道的基礎知識而我不知道,請見諒>//////< 希望有多點人一起玩玩看,不要輸給C/C++了XDDDD -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.112.46.73

05/14 22:31, , 1F
喔對了~還有MATLAB是有區分大小寫的..不要跟FORTRAN搞混了
05/14 22:31, 1F

05/14 22:45, , 2F
05/14 22:45, 2F

05/15 06:52, , 3F
不知道影像處理系統能不能搬過來呢@@?
05/15 06:52, 3F
影像處理我也不熟耶@@ 我記得有看過文章是說MATLAB核心內建的功能都可以使用 但是有些是屬於那些工具箱的,不是MATLAB原本就有的,就不一定了

05/15 06:54, , 4F
不過你為什麼當初不直接用MATLAB解決就好了呢?
05/15 06:54, 4F

05/15 08:57, , 5F
因為我只有一個小環節需要用到MATLAB的函數
05/15 08:57, 5F

05/15 08:58, , 6F
如果整個程式都用MATLAB會跑很慢 所以才會以FORTRAN為主
05/15 08:58, 6F

05/15 13:42, , 7F
推~~ matlab蠻吃資源的,用fortran跑長時間疊代就有感覺
05/15 13:42, 7F

05/15 16:31, , 8F
好棒,也許這樣就能直接用inverse和eigenvalue了
05/15 16:31, 8F

05/15 18:58, , 9F
若不考慮多核心,fortran inv也只比matlab inv慢一點
05/15 18:58, 9F

05/15 20:51, , 10F
太棒了! 感謝分享
05/15 20:51, 10F

05/16 00:46, , 11F
感謝分享
05/16 00:46, 11F

05/16 12:51, , 12F
推!
05/16 12:51, 12F

05/16 13:12, , 13F
感謝分享!!
05/16 13:12, 13F
IMSL有的函數基本上還是使用IMSL會比較快 姑且不論同樣的數值方法,MATLAB和FORTRAN誰的內建函數算得較快 光是從FORTRAN程式開始呼叫MATLAB,到完全啟動MATLAB計算引擎,就需要一點時間了 然後還要在FORTRAM、MATLAB間傳遞參數,也需要多執行一些指令 所以如果數據交換量大、交換頻率高的話 ,時間上反而沒效率 簡單說就是FORTRAN跟MATLAB間的溝通會耗費掉一些時間,每次都要花個幾秒鐘之類的 當然,如果程式是只跑幾分鐘或一兩個小時就跑完的那種, 或是整個程式就只有呼叫MATLAB那一兩次,其實是不差那幾秒的 其實如果只是要數值分析的功能的話,基本上IMSL都有了... ※ 編輯: callmei 來自: 140.112.218.94 (05/17 05:26)

05/17 13:35, , 14F
推教學!!
05/17 13:35, 14F
文章代碼(AID): #1Dpe-NWv (Fortran)
文章代碼(AID): #1Dpe-NWv (Fortran)