2016-07-06 17 views
0

FortranからCに3D配列を転送する際に問題があります。配列のサイズ(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を自由に使用できますか?それはたくさんの質問です。 – 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の配列は、コンパイル時に決定された固定の次元を持ちます。したがって、関数の宣言はコンパイルされません。配列ディメンションパラメータで次元ポインタを逆参照することを意図している場合、実行可能コードではないため、これは機能しません。コンパイルにのみ使用されるパラメータ宣言です。

第2に、呼び出しごとに異なる次元を持つ配列を渡すか、あらかじめ配列内にいくつの要素があるかわからないようです。これを仮定すると、配列のアドレスを渡すだけでよい(次元が常に正しいと仮定して)。あなたの関数のプロトタイプが、その後することができますあなたの関数は(そう、あなたにポインタ演算を表示するには)次のように実装することができ

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プログラムに実装されていると仮定して1次元配列にマップしたものです;そうでない場合は、適切なポインタを使用しますが、原則は例と同じです)。私はこのコードの非常に表面的なテストを行い、ポインタの操作は手間がかかりエラーが発生しやすいことに注意してください!がんばろう。

今、これは二次的に重要ですが、私はそのポイントを作るべきだと感じています。私はなぜあなたがポインターとして配列の次元を渡したいか分からない。おそらくそれは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 - それ、助けてくれてありがとう。私も解決策を投稿してしまった。私が学んだことから、Fortranの値は参照で渡されるので、ポインタが必要です。また、関数名の後にアンダースコアが必要なのは、インターネットが私にしたことだからです:)もう一度ありがとう! – LeeVining

0

を私はこれを行うには把握できた最も簡単な方法は、1次元配列として配列を渡すことでした。次に、適切な次元で新しい3D配列を作成するc関数で、渡された1次元配列を使用してそれらを塗りつぶします。私は、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++; 
       } 
      } 
    } 

誰でもこのソリューションに関するコメントがあれば、お気軽にコメントしてください。私はそこにこれをどこかでやるより良い方法があると確信しています!

関連する問題