2016-07-06 160 views
0

我在將三維數組從Fortran傳輸到C時遇到問題。我有代表數組大小的變量(idim,jdim,kdim),但我很難寫一個C代碼接收具有這些值大小的數組。我將附上我現在擁有的Fortran & C代碼。將Fortran多維數組轉換爲C

FORTRAN:

! Transfer u,v,w to CPU 

    idim = imax_ - imin_ 
    jdim = jmax_ - jmin_ 
    kdim = kmax_ - kmin_ 
    CALL CUDA(idim,jdim,kdim,u,v,w) 

和C:

extern "C" void cuda_(int *idim, int *jdim, int *kdim, float U[*kdim][*jdim][*idim], float V[*kdim][*jdim][*idim], float W[*kdim][*jdim][*idim]) 
{ 

我的工作加速與GPU編程已經存在的代碼,但我還是比較新的節目,所以請考慮到這一點。

提前致謝!

+0

編程新手?新增Fortran和C以及指針和malloc和free?這是很多要問的。 – duffymo

+2

很可能是http://stackoverflow.com/questions/27582715/passing-a-two-dimentional-array-from-fortran-to-c –

+2

的重複如果你是新手編程學習走路,然後纔可以慢跑。學習如何在選擇的語言中傳遞參數/參數,然後學習如何在C和Fortran之間傳遞實體,然後才能將CUDA添加到混合中。從長遠來看,這將爲您節省很多痛苦。 –

回答

0

爲什麼FORTRAN程序中的函數名稱不一樣?我會在這兩個程序中使用相同的名稱,但也許這是FORTRAN相關的。我將使用您爲此答案編寫的C函數名稱,是的,我同意這對於初學者來說是相當重要的任務。這不會是一個完整的解決方案,但應該引導你在正確的方向(希望)。首先... C中的數組具有在編譯時確定的固定尺寸。所以你的函數聲明不會被編譯。如果您的意圖是取消引用數組維度參數中的維度指針,那麼這將不起作用,因爲它不是可執行代碼;這些參數聲明僅用於編譯。其次,看起來你想要傳遞一個數組可以有不同維度的數組,從一個調用到另一個調用,或者你事先不知道你的數組中有多少元素。假設這一點,你只需要傳遞數組的地址(假設你的維度總是正確的)。然後,您的函數原型可能是:

void cuda_(int *idim, int *jdim, int *kdim, float *U, float* V, float* W); 

你的功能可以實現如下(可以這麼告訴你的指針運算):

void cuda_(int *idim, int *jdim, int *kdim, float* U, float* V, float* W) 
{ 
    int i, j, k; 

    // Assuming you want to process each individual array 
    // items one after the other; this to show pointer arithmetic 

    for (i=0; i<*idim; i++) { 

    for (j=0; j<*jdim; j++) { 

     for (k=0; k<*kdim; k++) { 

      // Do whatever with the i,j,kth element; 
      // We assign unique values so you can check 
      // that this example accesses the right array elements    

      *(U + i * sizeof(float) + j * sizeof(float) + k) = i + j + k;   
      *(V + i * sizeof(float) + j * sizeof(float) + k) = 2*i + 2*j + 2*k; 
      *(W + i * sizeof(float) + j * sizeof(float) + k) = 3*i + 3*j + 3*k; 

     } 

    } 

    } 

    return; 
} 

當然,你需要徹底地測試此示例,使確定這是你真正打算做的事情,而且我確實正確地映射了3D數組(我將它映射到一個一維數組上,假定這是它在FORTRAN程序中的實現方式;否則,你將不得不出現與適當的指針arithmitic,但原則將與例子相同)。我對這段代碼做了很膚淺的測試,並被警告指針操作很棘手,容易出錯!祝你好運。

現在,這是次要的,但我覺得應該提出這一點。我不明白你爲什麼要傳遞數組維度作爲指針;也許這是FORTRAN的要求(也許你不能通過值/副本傳遞參數)。如果您可以通過複製傳遞參數(如參考反對),那麼我建議以下變化:

// Prototype: 

void cuda_(int idim, int jdim, int kdim, float* U, float* V, float* W); 

// Implementation: 

void cuda_(int idim, int jdim, int kdim, float* U, float* V, float* W) 
{ 
    int i, j, k; 


    for (i=0; i<idim; i++) { 

    for (j=0; j<jdim; j++) { 

     for (k=0; k<kdim; k++) { 

      *(U + i * sizeof(float) + j * sizeof(float) + k) = i + j + k;   
      *(V + i * sizeof(float) + j * sizeof(float) + k) = 2*i + 2*j + 2*k; 
      *(W + i * sizeof(float) + j * sizeof(float) + k) = 3*i + 3*j + 3*k; 

     } 

    } 

    } 

} 
+0

嗨clarasoft-it,感謝您的幫助。我最終也發佈了我的解決方案。從我所瞭解到的情況來看,Fortran值是通過引用傳遞的,因此指針是必需的。此外,在功能名稱後面需要下劃線,因爲互聯網告訴我要做:)再次感謝! – LeeVining

0

我能想出這樣做是爲了傳遞數組作爲一維數組的最簡單方法。然後在c函數中創建具有適當尺寸的新3D數組,然後使用傳遞的1 D數組填充它們。我將修改的數組設置爲與FORTRAN數組相同的方式引用,以便更容易地訪問數組。我會在下方附上我的C方案:

extern "C" void cuda_(double *ptr_u, double *ptr_v, double *ptr_w, int *nx, int *ny, int *nz) 
{ 


    //Creating new arrays for U,V,W 
    int i,j,k,imax,jmax,kmax,ct=0; 
    imax = *nx; 
    jmax = *ny; 
    kmax = *nz; 

    double V[imax][jmax][kmax], W[imax][jmax][kmax], U[imax][jmax][kmax]; 

    for (k = 0; k < kmax; k++) 
    { 
      for (j = 0; j < jmax; j++) 
      { 
       for (i = 0; i < imax; i++) 
       { 
        U[i][j][k] = ptr_u[ct]; 
        V[i][j][k] = ptr_v[ct]; 
        W[i][j][k] = ptr_w[ct]; 
        ct++; 
       } 
      } 
    } 

如果任何人有這個解決方案有任何意見,隨意評論。我確信有一個更好的方法可以在某處做到這一點!