C -array에 대한 Fortran 배열. 멍청한 매크로 트릭이 원했습니다
-
03-07-2019 - |
문제
이 '단순화'포트란 코드가 있습니다
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 기술이 있는지 궁금해하기 시작했습니다.
의견 있으십니까?
해결책
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);
당신은 기억을 통해 순차적으로 걷는 것입니다 a
그리고 b
실제로 열 순서로 배치됩니다. 그것은 그것에 끔찍합니다 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]
내가 위에서 제안한 것이 더 낫습니다.
다른 팁
당신의 Fortran 사람들이 올바르게했다고 확신합니까?
원래 게시 한 코드 스 니펫은 이미 배열에 Row-Major 순서로 배열에 액세스하고 있습니다 (Fortran의 경우 '비효율적 인', '효율적').
코드 스 니펫과 질문에서 언급 한 바와 같이,이 '올바른'을 얻는 것은 오류가 발생할 수 있습니다. 이와 같은 세부 사항에 대해 걱정하지 않고 Fortran 코드를 C로 포팅하는 것에 대해 걱정하십시오. 포트가 작동하는 경우-열 주문형 액세스가 행 주문 액세스에 대한 열표 액세스를 변경하는 것에 대해 걱정할 수 있습니다 (포트가 작동 한 후에도 실제로 중요하다면).
대학 밖에서 첫 번째 프로그래밍 작업 중 하나는 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
그렇지 않으면 당신은 Row-Major의 배열을 통해 행진하고 있습니다. 이는 매우 비효율적 일 수 있습니다.
적어도 나는 그것이 그것이 Fortran에있는 방법이라고 믿습니다. 오랜 시간이 걸렸습니다.
코드를 업데이트 한 것을 보았습니다 ...
이제 루프 제어 변수를 교체하여 행을 반복 한 다음 C로 변환하는 경우 열에 반복 내부를 반복 할 수 있습니다.