2014-10-13 3 views
0

최적화 할 fortran90 코드가 있습니다. 이제 외부 루프에서 구조체의 메모리 위치에 액세스 한 다음 중첩 루프에서 가장 깊은 구조체에 액세스하려고합니다. 이 같은 뭔가 : -fortran90 : 주소 지정 메모리 위치

샘플 포트란 루프 기존 버전

do i = 1, N 
    ii = some integer 
    jj = some other integer 
    do j = 1, M 
    c = a(ii, jj)%b(i) 
    enddo 
enddo 

가되고 있습니다

초 포트란 루프 - 나는 이것을 가지고

do i = 1, N 
    ii = some integer 
    jj = some other integer 
    pointertoa = &a(ii, jj) !I know it's not correct in fortran, that is the question! 
    do j = 1, M 
    c = pointertoa%b(i) 
    enddo 
enddo 

을 쓰고 싶은 것이 (샘플) 예상대로 작동하는 C 코드 :

W orking 메모리의 주소 C

#include <stdio.h> 

struct mem{ 
    int a; 
    struct mm{ 
    int b; 
    float v; 
    } mmm; 
}; 

void main(){ 

    struct mem *m, dum; 

    dum.a = 12; 
    dum.mmm.b = 5; 
    dum.mmm.v = 3.2; 

    m = &dum; //m is given dum memory address 

    printf("dum.a = %d\n", dum.a); 
    printf("dum.mmm.b = %d\n", dum.mmm.b); 
    printf("dum.mmm.v = %f\n", dum.mmm.v); 

    printf("m.a = %d\n", m->a); 
    printf("m.mmm.b = %d\n", m->mmm.b); 
    printf("m.mmm.v = %f\n", m->mmm.v); 

} 

질문의 몇 :

  1. 어떻게 당신은 내가 fortran90에서 C에서와 동일한 기능을 수행 할 것인가?
  2. 두 번째 포트란 루프가 코드 속도를 높일 것이라고 생각합니까?
+0

(2) 어떻게 코드 속도를 높일 수 있습니까? –

+0

Fortran에서 포인터는'&'대신'=>'에 의해 설정됩니다! –

+0

@JohnZwinck, 속도 향상은 일종의 _prefetching_ 일 것입니다 : 여러분은'ii'와'jj' 인덱스가 외부주기에 저장되어 있음을 볼 수 있습니다. 따라서'a (ii, jj) '를 같은 값에로드하는 것이 명백합니다 장소. @AlexanderVogt, 포인터가 간단히 작동하지 않습니다. 내부 사이클에서 (ii, jj)의 메모리 위치가 필요합니다. 값에 대한 참조가 아닙니다. 어쨌든 C 코드에서 포인터로 시도해 보았습니다. 설정 잘못 :). – bio

답변

2

포트란은 변수 또는 다른 것의 메모리 주소를 얻는 것을 매우 어렵게 만듭니다. 포인터와 메모리 주소로 엉망이되는 C로 배운 기술과 기법은 Fortran에서 지원되지 않습니다. 일반적으로 Fortran의 핵심 애플리케이션 도메인 내에서 필요하지는 않습니다. 귀하의 질문은 오히려 당신이 포트란에 C를 쓰려고한다는 것을 암시합니다. 하지마.

이제 가슴에서 꺼 냈습니다. 최근에 소개 된 associate 구조를 사용하여 원하는 것을 얻을 수 있습니다. 뭔가 같은

associate(pointertoa => a(ii, jj)) 
    do j = 1, M 
    c = pointertoa%b(i) 
    enddo 
    end associate 

이것이 효율성 목표를 달성했는지 나는 스쿠비가 아닙니다. 하지만 그렇게된다면 나는 놀랄 것이다. 배열 요소에 대한 액세스 최적화는 Fortran 컴파일러가 50 년 이상 동안 작업 해 왔으며 실제로 상당히 잘 수행되었습니다. OP 최초의 코멘트에 응답

편집, ...

당신이 확실히 사용할 수 있습니다 associate 컴파일러가 지원하는 경우. 그러나 누군가가 당신의 어깨를 들여다보고 90 스탠다드의 출판 이후에 포트란에 소개 된 어떤 특징을 사용한다면 당신을 머리에 심하게 맞히는 것이 당신에게 달려 있는지 여부는 당신에게 달려 있습니다. 컴파일러는 신경 쓰지 않으며 컴파일 된 코드도 아닙니다. associate은 표준의 일부이며 Fortran은 하위 호환성을 유지하는 매우 좋은 기록을 가지고 있으므로 향후 컴파일러가 뒤죽박죽 될 가능성은 매우 적습니다.

C 함수를 작성하는 데는 루프 언 롤링, 메모리 프리 페치, 다중 명령 파이프 라인, 벡터 연산, 공통 하위 식 제거 등 모든 이점이 있습니다. Fortran 컴파일러의 성능을 능가하는 C 함수를 작성하여 최적화를 11로 설정하면이를 증명할 수있는 데이터가 다시 제공되므로 모자를 먹을 것입니다.나는 다시 쓰고있는 동안

그리고는 내가 루프

do j = 1, M 
    c = pointertoa%b(i) 
    enddo 

이 거의 중복과 좋은 최적화 컴파일러는 한 번만 c = pointertoa%b(i)을 실행하는 코드를 만들 것입니다 있습니다.

+0

'associate'는 ** fortran 2003 **에서 도입 된 무언가입니다 ** .. 그리고 불행히도 ** fortran90 ** 코드를 최적화해야합니다! 어쨌든 fortran90에서 사용할 수 있습니까? 나는이 일을하기 위해 외부 C 함수를 작성하려고 노력할 것이라고 생각한다. 효율성에 관해서는 컴파일러의 현명함에 대해 옳았지 만 이전 의견에 답한대로 원하는대로 수행하면 'M'로드가 적습니다. – bio

+1

Fortran 90 포인터를 사용할 수도 있습니다 :'type (xx), ponter :: pointertoa; pointertoa => a (ii, jj)',하지만 실제로는 코드 효율의 감소가 예상되지만 증가하지는 않습니다. 컴파일러는'a (ii, jj) '의 주소를 두 번 이상 계산할 필요가 없다는 것을 알기에 충분히 똑똑합니다. –

+0

@HPM, 정말로 많은 감사합니다. 블라디미르 (Bradimir)가 제안한대로 Fortran 90 포인터를 사용 했으므로 의미있는 개선이 없습니다. 최적화 보고서 (-O3 플래그를 사용하여 ifort 15 사용)를 읽어야하지만 필연적으로 속도는 향상되지 않습니다. 물론이 코드의 속도를 높이기 위해 모든 종류의 기술을 사용하고 있습니다. 예를 들어 벡터화 플래그를 사용하여 실제로 개선 된 것을 보았습니다. 그렇지만 한 걸음 물러서서 직렬 스칼라 코드가 최고인지 확인하기로했습니다. 가질 수 있습니다. 모자를 남길 수 있습니다. :) – bio