2012-04-10 22 views
4

我有一些fortran代碼與intel fortran編譯器ifort編譯。當我使用gprof配置文件測試,我得到的大部分時間在IO操作時,我想找到文件的末尾,但我沒有找到任何這更多的文檔:Fortran代碼的gprof輸出中的_IO_wfile是什麼?

index % time self children called  name 
               <spontaneous> 
[1]  20.6 0.07 0.00     _IO_wfile_seekoff [1] 
----------------------------------------------- 
               <spontaneous> 
[2]  20.6 0.07 0.00     sforcepf_ [2] 
----------------------------------------------- 
               <spontaneous> 
[3]  20.6 0.02 0.05     _IO_wfile_underflow [3] 
       0.01 0.04 258716/258717  strncmp [4] 
----------------------------------------------- 
       0.00 0.00  1/258717  _IO_wdefault_doallocate [15] 
       0.01 0.04 258716/258717  _IO_wfile_underflow [3] 
[4]  14.7 0.01 0.04 258717   strncmp [4] 
       0.04 0.00 3104592/3109256  strerror_r [5] 
----------------------------------------------- 
       0.00 0.00 4664/3109256  __strcmp_sse42 [14] 
       0.04 0.00 3104592/3109256  strncmp [4] 
[5]  11.8 0.04 0.00 3109256   strerror_r [5] 
----------------------------------------------- 

所以,問題是,這是IO特定於Linux,還是ifort或fortran?我正在嘗試優化此代碼,並且在Google中找不到有關此術語的有用信息。

回答

9

您編寫Fortran語句。英特爾Fortran編譯器將這些語句轉換爲彙編程序,包括對系統函數的調用。例如,strncmp是用於比較部分字符串的ISO C標準函數。因此,看起來您正在編寫Fortran語句來比較字符串,並且英特爾Fortran編譯器正在調用現有函數來實施比較。其中一些系統功能本身將通過調用您平臺上提供的更基本的功能(部分)來實現。

gprof向您展示了對您在編譯產品中引用的函數的調用。你看到的大部分是特定於Linux I/O的 - 在Windows機器上,I/O將使用具有不同名稱的類似函數。您可能看到一些特定於英特爾編譯器的內容,即所有英特爾編譯器都使用相同的(英特爾創建的)函數來執行某些操作,並且該函數使用特定於平臺的低級函數。

除非您準備重寫這些低級函數,並冒着將其用於其他程序的風險,使用相同的函數,那麼您可以進行的唯一優化就是不經常調用它們。例如,如果您有理由認爲讀取文件末尾是一種昂貴的I/O操作,並且如果您的程序策略是讀取文件,直到讀完文件並處理出現的錯誤,那麼你可能想要實施一個優秀的計劃戰略。這比重寫低層I/O例程來處理策略後果要容易。

3

假設你寫在任何語言

loop for a long time 
    write something to somewhere 

以下,並與gprof的簡介它。

gprof在IO或任何其他阻塞狀態期間暫停採樣。 這個程序所花費的時間非常少,但是花費的週期很多,其中大部分都花費在內置庫例程中,這些例程啓動IO並等待它完成。

所以如果你的程序是這樣的話,這就是你所看到的並不奇怪。

There's a lot more to this issue.

3

看起來像你看到的Fortran I/O操作。格式化的I/O在ifort中很慢。如果使用標準輸入/標準輸出重定向,則會變得更糟;而且管道更糟 - 英特爾文檔特別警告不要這樣做。 gfortran幾乎沒有那麼糟糕,但仍然非常緩慢。

一些可能性是:儘可能少的I/O調用盡可能

  • 嘗試做(例如移動它們移出循環
  • 避免重定向)和讀/寫文件,而不是直接
  • 檢查blocksizebuffercount和其他I/O相關的選項open()

如果這還不夠,和I/O是你的主要瓶頸,您可以考慮:

  • 尋找到流的I/O ifort,它更快,你可以做這樣的事情緩衝自己,以避免多次調用。但是,它可能會引入可移植性問題,因爲其他編譯器可能不支持它或者以不同方式執行。不要在標準輸入/輸出上執行(可能在ifort中工作,但它沒有記錄,並且不會與其他編譯器一起工作)。
  • 使用iso_c_binding來調用C函數 - 例如,如果您正在寫入標準輸出,則可以從libc中調用puts()。由於它是標準的,它甚至更快,實際上非常便於攜帶,實際上每個操作系統上的每個編譯器(Win32/linux64/sparc solaris)都需要(並自動鏈接)libc;但它相當醜陋,你必須照顧自己的空終止(例如通過編寫一個包裝函數),這會掩蓋代碼並可能引發錯誤。
  • 不要將這些方法中的任何一種與常規I/O混合在同一個文件上!

如果您在代碼中明確地進行字符串比較,則最終還會調用strncmp()。字符串操作在ifort方面也有點慢(雖然遠不及I/O),所以如果你在做比較,你可能會通過直接調用strncmp()獲得幾秒鐘的時間,但是我會建議反對 - 收益並不是那麼大,並且它再次掩蓋了代碼。

+0

謝謝你們,我從這個主題中學到了很多東西。 – Gabriel 2012-04-23 15:44:10