【问题标题】:Fortran Array to C array. Stupid macro tricks wantedFortran 数组到 C 数组。需要愚蠢的宏观技巧
【发布时间】:2010-09-18 15:55:06
【问题描述】:

我有这个“简化”的 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

一位编程大师警告我,fortran 按列顺序高效访问数据,而 c 按行顺序有效访问数据。他建议我仔细看一下代码,并准备好切换循环以保持旧程序的速度。

作为一个懒惰的程序员,我认识到所涉及的时间以及我可能犯的错误,我开始想知道是否有一种#define 技术可以让我安全、轻松地转换此代码。

你有什么建议吗?

【问题讨论】:

  • 另一个你可能犯的错误示例:让 J=200(其范围为 1 到 200)和 I=100(范围为 1 到 100),这将是最后一个嵌套循环,它将执行 A(200,100) = B(200,100)--哎呀!您已将两个数组声明为 (100, 200)。你的编译器可能会抱怨......

标签: c arrays c-preprocessor


【解决方案1】:

您确定您的 FORTRAN 人员做对了吗?

您最初发布的代码 sn-p 已经以行优先顺序访问数组(这对于 FORTRAN 来说是“低效的”,对于 C 来说是“高效的”)。

正如代码的 sn-p 所示以及您的问题中提到的那样,得到这个“正确”可能容易出错。担心首先将 FORTRAN 代码移植到 C 中,而不用担心这样的细节。当端口工作时 - 然后您可以担心将列顺序访问更改为行顺序访问(如果在端口工作之后它甚至真的很重要)。

【讨论】:

    【解决方案2】:

    我大学毕业后的第一份编程工作是修复一个从 FORTRAN 移植的长期运行的 C 应用程序。阵列比您的阵列大得多,每次运行大约需要 27 小时。修好后,它们在大约 2.5 小时内运行……非常棒!

    (好吧,确实没有分配,但我很好奇,发现他们的代码有一个大问题。尽管有这个修复,一些老前辈还是不太喜欢我。)

    这里似乎发现了同样的问题。

    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 时在列中迭代。

    【讨论】:

    • 这是一个人为的例子,目的是让事情变得不那么复杂。我希望不必通过一些宏技巧来更改数千行代码中的循环。
    【解决方案3】:

    在 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]
    

    会比我上面的建议更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-26
      • 2014-07-07
      • 2011-06-16
      • 2011-08-12
      • 2019-03-16
      • 1970-01-01
      • 2011-11-29
      相关资源
      最近更新 更多