2013-07-01 2 views
1

저는 fortran과 gfortran을 처음 보았습니다. 전체 식 배열은 병렬로 계산된다는 것을 알았지 만 계산은 내 컴퓨터의 한 핵심에서만 발생합니다.전체 배열 표현식을 사용할 수 있습니까?

program prueba_matrices 

implicit none 

integer, parameter        :: num = 5000 
double precision, dimension(1:num,1:num)  :: A, B, C 
double precision, dimension (num*num)   :: temp 
integer        :: i 

temp = (/ (i/2.0, i=1,num*num) /) 
A = reshape(temp, (/ num, num/)) 
B = reshape(temp, (/ num, num/)) 
C = matmul(A , B) 

end program prueba_matrices 

이 같은 complie :

내가 다음 코드를 사용하여 그놈 시스템 모니터에서 실시간으로 생성되는 그래프를보고,

gfortran prueba_matrices.f03 -o prueba_gfortran 

을, 나는 볼 수있다 하나의 핵심 작업입니다. 내가

C = A * B 

의 계산으로 라인

C = matmul(A , B) 

를 대체 할 경우이 같은 동작을 얻을 수 있습니다.

내가 뭘 잘못하고 있니?

+0

@HighPerformanceMark : 저는 그가 배열이 아닌 병렬 처리를 테스트하고 있다고 생각합니다. –

+0

gfortran이 전체 배열 표현식을 병렬로 실행한다는 그 진술을 어디서 보았습니까? –

+0

@HighPerformanceMark : 네, 두 문장이 같지 않다는 것을 압니다. KyleKanos가 말했듯이, 나는 병렬화를 테스트하고 있습니다. –

답변

2

GFortran/GCC에는 일부 자동 병렬화 기능이 있습니다 (http://gcc.gnu.org/wiki/AutoParInGCC 참조). 그것들은 자주 좋지 않으므로 -ON 최적화 수준에서 활성화되지 않으므로 -ftree-parallelize-loops = N으로 특별히 선택해야합니다. 여기서 N은 사용하려는 스레드의 수입니다. 그러나 위의 예에서 "A * B"와 같은 루프는 메모리 대역폭 (충분히 큰 배열의 경우)에 의해 제약을받을 가능성이 높기 때문에 코어를 추가하면 그만큼 도움이되지 않을 수 있습니다. 또한 MATMUL 내장 함수는 gfortran 런타임 라이브러리에서 구현됩니다.이 라이브러리는 autopar 옵션과 함께 컴파일되지 않습니다 (그렇게하지 않으면 특별히 빌드하지 않은 경우).

실제로 위의 예제 코드가 실제로 최적화를 사용하는 데 도움이 될 수 있습니다. -O3 Gfortran을 사용하면 벡터화가 자동으로 활성화되므로 여러 CPU 코어가 아닌 루프를 병렬화하는 방법으로 볼 수 있습니다.

+0

'-ftree-parallelize-loops = N' ** 루프 **를 병렬 처리하기위한 것으로, OP는 단지 1입니다. 이것은 matmul (A, B)에 도움이되지 않을 것입니다. –

+1

@KyleKanos : 실제로, MATMUL 구현이 라이브러리 루틴이라는 내 문장이 암시 적으로 이미 그 지점을 만들었다 고 생각했습니다. – janneb

+0

필자의 요점은 프로그램이 루프 부분보다 코드의 'matmul'부분에 더 많은 시간을 소비한다는 것입니다 (5000 -> 1500 및 컴파일 옵션 없음, 루프의 경우 0.05 초, 초 'matmul' 계산!). 루프 병렬화에서 저장 될 시간은 언제나 위의 전체 코드와 완전히 무관 할 것입니다. –

1

당신이 인용 한 코스의 핵심 문장은 "배열 할당을 통해 개별 과제의 암시적인 순서는 없으며 개념적으로 병렬로 수행됩니다."라고 생각합니다. 핵심 단어는 "개념적으로"입니다. 전체 배열 표현식이 실제로 병렬로 실행된다는 것은 아닙니다. 하나 이상의 코어가 사용될 것으로 예상해서는 안됩니다. 이를 위해서는 OpenMP 또는 MPI (Fortran 자체 외부) 또는 Fortran 2008의 코어 어레이를 사용해야합니다.

EDIT : Fortran은 Fortran 2008의 코어 어레이까지 실제 병렬 실행을 지원하지 않았습니다 일부 컴파일러는 병렬 처리를 제공하고 일부 언어 기능은 컴파일러가 병렬 실행 (선택적)을 구현하는 것을 더 쉽게 만듭니다. 제가 웹 기사에서 인용 한 문장은 당신이 인용 한 부분보다 현실을 더 잘 나타냅니다. 전체 배열 표현식은 병렬 실행을 요구하지 않았습니다. 프로그래머가 문법적으로 편리하게 사용할 수 있으므로 언어를 더 높은 수준으로 만들 수 있으므로 do 루프를 작성하지 않고 배열 연산을 단일 명령문으로 표현할 수 있습니다. 어떤 경우에도 웹상의 기사가 확실하지 않습니다. 병행 실행 부족에 대한 당신의 관찰은 어떤 진술이 정확한지 보여줍니다. Fortran 언어와 모순되지 않습니다.

+0

그렇습니다. 그러나 위의 과제는 다음과 같습니다. ! * 2! 안으로 || B (-3,0) = C (2,1) * D (1,0) -B (-3,0) ** 2! 안으로 || ... B (-4,1) = C (1,2) * D (0,1) - B (-4,1) ** 2! 안으로 || ... B (0,2) = C (5,3) * D (4,2) -B (0,2) ** 2! 안으로 || ! END PARALLEL ' –

+0

고맙습니다. 편집이 매우 명확합니다. –

2

gfortran에서 matt를 호출하여 다중 스레드로 만들려면 multithreading 지원으로 컴파일 된 외부 BLAS 패키지로 간단하게 링크하는 것이 가장 쉽습니다.지원자는 OpenBlas (nee Goto Blas), ATLAS 또는 Intel의 MKL, AMD의 ACML 또는 Apple의 가속 프레임 워크와 같은 상용 패키지를 포함합니다. 그래서 예를 들면

, 간단한 예를 들어베이스 matmul 함께

program timematmult 

    real, allocatable, dimension(:,:) :: A, B, C 
    integer, parameter :: N = 2048 

    allocate(A(N,N)) 
    allocate(B(N,N)) 
    allocate(C(N,N)) 

    call random_seed 
    call random_number(A) 
    call random_number(B) 

    C = matmul(A,B) 

    print *, C(1,1) 

    deallocate(C) 
    deallocate(B) 
    deallocate(A) 

end program timematmult 

여기 특히

$ gfortran -o matmult matmult.f90 -fexternal-blas -lgoto2 
$ time ./matmult 
    514.38696 

real 0m0.564s 
user 0m2.202s 
sys  0m0.964s 

참고

$ gfortran -o matmult matmult.f90 
$ time ./matmult 
    514.38751 

real 0m6.518s 
user 0m6.374s 
sys  0m0.021s 

및 멀티 스레드 gotoblas 라이브러리

실시간이 사용자 시간보다 짧아서 여러 개의 코어가 사용되고 있음을 나타냅니다.

+0

고맙다. 나는 이것을 시험해야만한다. –

+0

안녕하세요, 내 컴파일러는 goto2 라이브러리를 찾지 못했습니다. 어떤 패키지를 설치해야합니까 (저는 Ubuntu 12.04 LTS를 사용합니다). –

+0

문제의 라이브러리가 외부 BLAS 패키지에 있음을 알고 있습니다. 패키지 관리자가 설치하지 않았기 때문에 외부이지만 컴파일되었습니다. 고맙습니다. –

관련 문제