2012-07-04 63 views
0

我想在Fortran 90中獲得靈活的(編譯時定義的)存儲順序。爲此,我試圖使用包括一些增強pp頭的C++預處理器。使用C++預處理器在Fortran中編譯時定義的存儲順序

因此,舉例來說,而不是訪問三維陣列是這樣的:

myArray(k,i,j) 

我想有這樣的:

myArray(POINT3D(i,j,k)) 

,並確定在編譯時訪問的順序。

現在我已經試過:

#include "boost_pp_cat.hpp" 
#include "boost_pp_comma.hpp" 

! ------ Define storage orders here --------- ! 
!Forward lookup {i,j,k} <- {1,2,3} 
#define KIJ_ORDER_ARG1 k 
#define KIJ_ORDER_ARG2 i 
#define KIJ_ORDER_ARG3 j 

! ------ Switch between storage orders ------ ! 
#define CURR_ORDER KIJ_ORDER 

! ------ Generate all required macros ------- ! 
#define STOR_ORDER_ARG(storOrder, argNum) BOOST_PP_CAT(BOOST_PP_CAT(storOrder, _ARG), argNum) 

#define CHOOSE_PARAM(storOrder, argNum) BOOST_PP_CAT(STOR_ORDER_ARG(storOrder, argNum), Param) 

#define POINT3D(iParam, jParam, kParam) POINT3D_WITH_STORORDER(CURR_ORDER, iParam, jParam, kParam) 

#define POINT3D_WITH_STORORDER(storOrder, iParam, jParam, kParam)  POINT3D_WITH_STORORDER_PRE(storOrder) 
#define POINT3D_WITH_STORORDER_PRE(storOrder) CHOOSE_PARAM(storOrder, 1), CHOOSE_PARAM(storOrder, 2), CHOOSE_PARAM(storOrder, 3) 

這將擴大

myArray(POINT3D(i,j,k)) 

myArray(kParam, iParam, jParam) 

幾乎在那裏!現在我的問題:

  1. 是否有可能做我想要使用C預處理器?
  2. 如果不是 - 你會用什麼技術? (我正在考慮製作我自己的專門的「預處理器」python腳本,但你有另一個建議嗎?)

回答

0

如果有人讀這個:我在下面解決了解決方案。不夠優雅,可擴展或可重用,但它完成了工作,並讓我使用不帶擴展名的'標準'fortran預處理器(由於可以顯示原始文件的行號,因此必須調試代碼時纔有大的優勢)。

! ------ Define storage orders here --------- ! 
#define IJK_ORDER 1 
#define KIJ_ORDER 2 
#define IKJ_ORDER 3 
! ------ Switch between storage orders ------ ! 
#ifdef GPU 
    #define CURR_ORDER IJK_ORDER 
#else 
    #define CURR_ORDER KIJ_ORDER 
#endif 

! ------ Order dependent macros ------------- ! 
#if (CURR_ORDER == KIJ_ORDER) 
    #define AT(iParam, jParam, kParam) kParam, iParam, jParam 
#elif (CURR_ORDER == IKJ_ORDER) 
    #define AT(iParam, jParam, kParam) iParam, kParam, jParam 
#else 
    #define AT(iParam, jParam, kParam) iParam, jParam, kParam 
#endif 

! ------ general macros --------------------- ! 
!note: this is just a rename. Same syntax can be used for domain definition and array access 
!-> give it two seperate names to make the intention of the code clearer 
#define DOM(iParam, jParam, kParam) AT(iParam, jParam, kParam) 
1

1:我不知道,但個人我不會依賴預處理器無論如何,無論如何,

2:我會寫一個Fortran定義的類型沿着這些線路

type odd_storage_order_real_array 
     integer, dimension(3) :: permutation 
     real, dimension(:,:,:), allocatable :: elements 
     contains 
     procedure :: get_element_at 
    end type odd_storage_order_real_array 

,那麼你可以寫語句,如

type(odd_storage_order_real_array) :: an_array 
. 
. 
. 
an_array%get_element_at(1,2,3) 

在指定的位置,以獲得元素。你會注意到我沒有爲你寫出get_element_at函數,但是你的問題告訴我你不會自己寫任何麻煩。當然,它會使用permutation組件按照您的要求對索引進行重新排序。您可能需要一個相應的set_element_at函數,並且可以在內置陣列中進行「類型轉換」。

如果您想爲任何級別的陣列,單式,扁平它們像這樣:

type odd_storage_order_real_array 
    integer, dimension(:), allocatable :: permutation 
    real, dimension(:), allocatable :: elements 
    contains 
    procedure :: element_at 
end type odd_storage_order_real_array 

編輯

響應OP的評論。我仍然不會使用預處理器。

我想我在這種情況下做的事情就是編寫一個函數,將數組從其「自然」順序轉置(按照你喜歡的尺寸一般化),然後編寫該函數的反函數太。初始化時應用函數,完成反函數;執行成本不應該很大。這是否適合您的應用程序的模式,我不知道。

我真正想做的是嘗試幾個變化,看看哪一個給了我最好的性能比例:可編程性;換句話說,對於難以讀取(以及不可維護等)的限制,我會在搜索速度時製作一個HPC代碼。

+0

感謝您的回答。有一些我還沒有提到:這應該是HPC的任務。如果訪問器可以被內聯並被編譯器擴展爲常量,那麼你的答案可能是適用的,否則它會損害性能。那麼我將不得不測試它。 –