程式碼中的追蹤程序
您可以指示編譯器插入追蹤 您已定義的程序 的呼叫,以協助除錯或計時執行其他程序。
若要追蹤程式中的程序,您必須指定要追蹤的程序。 您也必須提供自己的追蹤程序。 如果您在不提供追蹤程序的情況下啟用追蹤,則會收到鏈結器錯誤,有關稱為 __func_trace_enter、 __func_trace_exit及可能 __func_trace_catch的未定義符號。
指定要追蹤的程序
-qfunctrace 編譯器選項可控制程式中所有 非行內使用者定義程序 及所有概述編譯器產生程序的追蹤。 如果您有興趣追蹤特定的外部或模組程序,您可以使用 -qfunctrace+ 和 -qfunctrace- 編譯器選項。 您也可以指定 NOFUNCTRACE 指引,以停用追蹤整個模組、外部程序、模組程序或內部程序。
可以追蹤的內容
追蹤適用於程式、外部程序、 非本質 模組程序及內部程序。
除非針對概述的使用者程式碼 (例如 OpenMP 程式) 產生編譯器產生的程序,否則不會追蹤這些程序。 在這些情況下,概述程序的名稱會包含原始使用者程序的名稱作為字首。
無法追蹤行內程序及陳述式函數,因為它們不存在於執行檔中。
為了避免無限遞迴,無法追蹤使用者定義的追蹤程序。 同樣地,對於從使用者定義的追蹤程序呼叫的程序,必須停用追蹤。
如何撰寫追蹤程序
您可以在 Fortran、C 或 C++ 中實作追蹤程序。
SUBROUTINE routine_name(procedure_name, file_name, line_number, id)
USE, INTRINSIC :: iso_c_binding
CHARACTER(*), INTENT(IN) :: procedure_name
CHARACTER(*), INTENT(IN) :: file_name
INTEGER(C_INT), INTENT(IN) :: line_number
TYPE(C_PTR), INTENT(INOUT) :: id
END SUBROUTINE其中 routine_name 是外部或模組程序的名稱。- 使用 -qfunctrace_xlf_enter、 -qfunctrace_xlf_exit或 -qfunctrace_xlf_catch 編譯器選項。
- 使用 FUNCTRACE_XLF_ENTER、 FUNCTRACE_XLF_EXIT或 FUNCTRACE_XLF_CATCH 指引。
當您指定這些選項或指引時, XL Fortran 會產生稱為 __func_trace_enter、 __func_trace_exit和 __func_trace_catch 的封套程序,以呼叫對應的追蹤程序。 這些 wrapper 可透過將虛擬引數從 C 原型轉換至先前說明的介面,來與 C 及 C++ 進行交互作業。 因此, routine_name 不得命名為 __func_trace_enter、 __func_trace_exit或 __func_trace_catch。 此外,您的程式不得包含多個追蹤程序。
__func_trace_enter、 __func_trace_exit及 __func_trace_catch 程序。 它們必須具有下列原型:void __func_trace_enter(const char *const procedure_name, const char *const file_name, int line_number, void **const id);void __func_trace_exit(const char *const procedure_name, const char *const file_name, int line_number, void **const id);void __func_trace_catch(const char *const procedure_name, const char *const file_name, int line_number, void **const id);
extern "C"。XL Fortran 會在程序進入和結束時插入對追蹤程序的呼叫。 它會傳遞所追蹤的程序名稱、包含所追蹤之進入或跳出點的檔案名稱,以及行號。 它也會傳遞在程式開頭起始設定為 C_NULL_PTR 的靜態指標位址。 此指標可讓您在進入追蹤程序中儲存任意資料,並在結束及捕捉程序中存取此資料。 如需詳細資料,請參閱「範例」一節。 因為此指標位於靜態記憶體中,所以在追蹤執行緒或遞迴程序時可能需要額外步驟。
範例追蹤程序
- tracing_routines.c: 提供以 C 撰寫的追蹤程序。 當您不需要存取 Fortran 模組,且有可能遞迴輸入/輸出時,此檔案非常有用。
- tracing_routines.f90: 提供以 Fortran撰寫的追蹤程序。 當您需要存取追蹤程序中的 Fortran 模組或本質時,這個檔案很有用。
> cat helloworld.f
print *, 'hello world'
end
> cc -c /opt/IBM/xlf/15.1.0/samples/functrace/tracing_routines.c
> xlf95 helloworld.f -qfunctrace tracing_routines.o
** _main === End of Compilation 1 ===
1501-510 Compilation successful for file helloworld.f.
> ./a.out
{ _main (helloworld.f:1)
hello world
} _main (helloworld.f:2)
>追蹤限制
- 程序無法與其 ENTRY 點分開追蹤。 全部都被追蹤或沒有任何追蹤。 即使在追蹤 ENTRY 點時,也會將程序名稱傳遞給追蹤程序。 行號可協助識別在此情況下正在追蹤的項目。
- Fortran 標準需要純程序無負面影響。 編譯器在最佳化程式時使用此假設。 如果您啟用純程序的追蹤,則追蹤程序不得以產生負面影響的方式變更程式狀態。
- Fortran 標準強制限制遞迴輸入/輸出。 如果您在 Fortran中撰寫追蹤程序,則必須小心不要違反這些規則。下列範例具有列印陳述式,其中 I/O 項目是函數呼叫 (foo) 的結果。 在此情況下,追蹤程序在外部檔案上具有 I/O 是不合法的:
> cat recursive.f integer function test() test = 1 end function integer test print *, test() ! test must not have I/O on external unit end > xlf95 -c /opt/IBM/xlf/15.1.0/samples/functrace/tracing_routines.f90 ** my__func_trace_enter === End of Compilation 1 === ** my__func_trace_exit === End of Compilation 2 === ** my__func_trace_catch === End of Compilation 3 === 1501-510 Compilation successful for file tracing_routines.f90. > xlf95 recursive.f tracing_routines.o -qfunctrace ** test === End of Compilation 1 === ** _main === End of Compilation 2 === 1501-510 Compilation successful for file recursive.f. > ./a.out { _main (recursive.f:6) XL Fortran (I/O initialization): I/O recursion detected. IOT/Abort trap > - 當最佳化您的程式時,編譯器會重新排序程式碼並移除已停用的程式碼。 因此,當啟用最佳化時,傳遞至追蹤程序的行號可能不精確。
範例
my_enter 和 my_exit 作為追蹤程序。 NOFUNCTRACE 指引用來停用 main_program的追蹤:> cat example.f
! Designate my_enter as a tracing procedure that should be called
! on procedure entry
!ibm* functrace_xlf_enter
subroutine my_enter(procedure_name, file_name, line_number, id)
use, intrinsic :: iso_c_binding
use, intrinsic :: xlfutility
character(*), intent(in) :: procedure_name, file_name
integer(c_int), intent(in) :: line_number
type(c_ptr), intent(inout) :: id
integer(kind=time_size), pointer :: enter_count
! Store the time we entered the procedure being traced into id.
if (.not. c_associated(id)) then
allocate(enter_count)
enter_count = time_()
id = c_loc(enter_count)
end if
print *, 'Entered procedure ', procedure_name, ' at ( ', &
file_name, ' :', line_number, ').'
end subroutine
! Designate my_exit as a tracing procedure that should be called
! on procedure exit
!ibm* functrace_xlf_exit
subroutine my_exit(procedure_name, file_name, line_number, id)
use, intrinsic :: iso_c_binding
use, intrinsic :: xlfutility
character(*), intent(in) :: procedure_name, file_name
integer(c_int), intent(in) :: line_number
type(c_ptr), intent(inout) :: id
integer(kind=time_size), pointer :: enter_count
integer(kind=time_size) exit_count, duration
! id should have been associated in my_enter with the time we
! entered the procedure being traced. Find the elapsed time.
if (c_associated(id)) then
exit_count = time_()
call c_f_pointer(id, enter_count)
duration = exit_count - enter_count
else
stop "error!"
endif
print *, 'Leaving procedure ', procedure_name, ' at ( ', &
file_name, ' :', line_number, ').'
print *, 'Spent', duration, 'seconds in ', procedure_name, '.'
end subroutine
! sub2 will be traced
subroutine sub2
call sleep_(3)
end subroutine
! sub1 will be traced
subroutine sub1
call sleep_(5)
call sub2
end subroutine
! Do not want to trace main_program
!ibm* nofunctrace
program main_program
call sub1
end program
> xlf95 example.f -qfunctrace
** my_enter === End of Compilation 1 ===
** my_exit === End of Compilation 2 ===
** sub2 === End of Compilation 3 ===
** sub1 === End of Compilation 4 ===
** main_program === End of Compilation 5 ===
1501-510 Compilation successful for file example.f.
> ./a.out
Entered procedure sub1 at ( example.f : 59 ).
Entered procedure sub2 at ( example.f : 54 ).
Leaving procedure sub2 at ( example.f : 55 ).
Spent 3 seconds in sub2.
Leaving procedure sub1 at ( example.f : 61 ).
Spent 8 seconds in sub1.
>相關資訊
- 如需 -qfunctrace 編譯器選項的詳細資料,請參閱 XL Fortran 編譯器參照中的 -qfunctrace 。
- 如需 -qfunctrace_xlf_catch、 -qfunctrace_xlf_enter或 -qfunctrace_xlf_exit 編譯器選項的詳細資料,請參閱 XL Fortran 編譯器參照中 XL Fortran 編譯器選項的詳細說明 一節。
- 如需 FUNCTRACE_XLF_CATCH、 FUNCTRACE_XLF_ENTER和 FUNCTRACE_XLF_EXIT 指引的詳細資料,請參閱 XL Fortran Language Reference中的 詳細指引說明 一節。
- 如需 NOFUNCTRACE 指引的詳細資料,請參閱 XL Fortran Language Reference中的 NOFUNCTACE 。