4

私はこの「簡略化された」fortranコードを持っています

real B(100, 200) 
real A(100,200)

... initialize B array code.

do I = 1, 100
  do J = 1, 200
    A(J,I) = B(J,I)
  end do
end do

プログラミングの第一人者の 1 人は、fortran は効率的に列の順序でデータにアクセスするのに対し、c は行の順序で効率的にデータにアクセスすると警告しました。彼は、コードをよく見て、古いプログラムの速度を維持するためにループを切り替える準備をすることを提案しました。

私は怠惰なプログラマーであり、日々の努力と犯しがちな間違いを認識しているため、このコードを安全かつ簡単に変換できる #define 手法があるのではないかと考え始めました。

何か提案はありますか?

4

3 に答える 3

4

C では、多次元配列は次のように機能します。

#define array_length(a) (sizeof(a)/sizeof((a)[0]))
float a[100][200];
a[x][y] == ((float *)a)[array_length(a[0])*x + y];

言い換えれば、それらは本当にフラットな配列であり、[][]単なるシンタックス シュガーです。

これを行うとします:

#define at(a, i, j) ((typeof(**(a)) *)a)[(i) + array_length((a)[0])*(j)]
float a[100][200];
float b[100][200];
for (i = 0; i < 100; i++)
    for (j = 0; j < 200; j++)
        at(a, j, i) = at(b, j, i);

あなたはメモリを順番に歩いていて、そのふりをしてab実際には列優先の順序でレイアウトされています。そういうところはちょっと怖いですがa[x][y] != at(a, x, y) != a[y][x]、こうやって騙されているということを覚えておけば大丈夫です。

編集

男、私はばかげているように感じます。この定義の意図は を作ることat(a, x, y) == at[y][x]であり、実際にそうしています。そのため、はるかにシンプルで理解しやすい

#define at(a, i, j) (a)[j][i]

私が上で提案したものよりも良いでしょう。

于 2008-10-23T14:23:10.030 に答える
4

あなたの FORTRAN 関係者は正しいことをしたと確信していますか?

最初に投稿したコード スニペットは、既に行優先順で配列にアクセスしています (これは、FORTRAN では「非効率的」、C では「効率的」です)。

コードのスニペットで示され、質問で述べたように、これを「正しく」取得するとエラーが発生しやすくなります。このような詳細を気にせずに、最初に FORTRAN コードを C に移植することを心配してください。ポートが機能している場合 - 列順のアクセスを行順のアクセスに変更することについて心配することができます (ポートが機能した後に本当に問題になる場合)。

于 2008-10-22T21:43:48.517 に答える
2

大学を出たときの最初のプログラミングの仕事の 1 つは、FORTRAN から移植された長時間実行される C アプリケーションを修正することでした。アレイはあなたのものよりもはるかに大きく、実行ごとに約 27 時間かかりました。修正後、約 2.5 時間で実行されました。

(OK、実際には割り当てられていませんでしたが、興味があり、コードに大きな問題があることがわかりました。この修正にもかかわらず、古いタイマーの一部は私をあまり好きではありませんでした。)

同じ問題がここで見つかったようです。

real B(100, 200) 
real A(100,200)

... initialize B array code.

do I = 1, 100
  do J = 1, 200
    A(I,J) = B(I,J)
  end do
end do

あなたのループ(良いFORTRANであるために)は次のようになります:

real B(100, 200) 
real A(100,200)

... initialize B array code.

do J = 1, 200
  do I = 1, 100
    A(I,J) = B(I,J)
  end do
end do

そうしないと、行優先で配列を行進することになり、非常に非効率になる可能性があります。

少なくとも、FORTRAN ではそうなるだろうと私は信じています。


コードを更新したのを見ました...

ここで、C に変換する場合は、ループ制御変数を交換して、行を反復し、その内部で列を反復するようにします。

于 2008-10-22T21:54:53.753 に答える