2016-07-15 5 views
1

Intel MKL을 처음 사용했습니다. 여기에 문제가 있습니다 - 분명히 MKL 자체와 관련이없는 문제입니다. 그러나 지금까지 알려지지 않은 크기의 배열을 선언하고 다른 서브 루틴으로 서브 루틴의 출력으로 전달하는 방법의 문제에 대한 문제입니다. 내가 PARDISO에 의해 호출에 적합한 자사의 CSR 형식으로 행렬을 변환 mkl_ddnscsr를 사용하기 위해 노력하고있어알 수없는 크기의 배열 (서브 루틴 출력)을 다른 서브 루틴으로 전달

:

CALL mkl_ddnscsr(job,Nt,Nt,Adns,Nt,Acsr,ja,ia,info) 

CALL PARDISO(pt,1,1,11,13,Nt,Acsr,ia,ja,perm,1,iparm,0,b,x,errr) 

문제는, 나는 CSR의 길이가 ACSR 인덱스를 형성 무슨 생각이 없다 벡터 mkl_ddnscsr 서브 루틴을 호출하기 전에 ja. 주 프로그램이나이 두 줄이있는 서브 루틴에서 Acsr과 ja를 어떻게 선언해야합니까?

나는 메인 프로그램에서 인터페이스 외부

INTEGER, ALLOCATABLE :: ja(:) 
REAL(KIND=8), ALLOCATABLE :: Acsr(:) 

다음

INTERFACE 
SUBROUTINE mkl_ddnscsr(job, m, n, Adns, lda, Acsr, ja, ia, info) 
IMPLICIT NONE 
INTEGER :: job(8) 
INTEGER :: m, n, lda, info 
INTEGER, ALLOCATABLE :: ja(:) 
INTEGER :: ia(m+1) 
REAL(KIND=8), ALLOCATABLE :: Acsr(:) 
REAL(KIND=8) :: Adns(:) 
END SUBROUTINE 
END INTERFACE 

같은 것을 시도했다. 그러나이 구성을 사용하면 실행 중 분할 오류가 발생합니다. 한편

, 내가

INTERFACE 
SUBROUTINE mkl_ddnscsr(job, m, n, Adns, lda, Acsr, ja, ia, info) 
IMPLICIT NONE 
INTEGER :: job(8) 
INTEGER :: m, n, lda, info 
INTEGER :: ja(:), ia(m+1) 
REAL(KIND=8) :: Acsr(:), Adns(:) 
END SUBROUTINE 
END INTERFACE 

다음

INTEGER, DIMENSION(:) :: ja 
REAL(KIND=8), DIMENSION(:) :: Acsr 

같은 그런 다음 ifort 나에게 다음과 같은 메시지를 줄 것이라고 시도하는 경우 :

error #6596: If a deferred-shape array is intended, then the ALLOCATABLE or POINTER attribute is missing; if an assumed-shape array is intended, the array must be a dummy argument. 

사람은 어떤 생각을 가지고 이 문제를 해결하는 방법? 주 프로그램 (또는 주요 서브 루틴)에서 ja와 Acsr을 선언하고이를 전달하는 올바른 방법은 무엇입니까?

서브 루틴은 인텔 MKL 패키지의 일부이며, 독자적으로 쓰는 것이 아니므로 module은 문제가되지 않습니다.

+1

태그 fortran을 사용하십시오. 제목에서 반복 할 필요는 없습니다. 'kind = 8'은 추악한 코드 냄새입니다 –

답변

1

의 인터페이스는 manual page에서 찾을 수 있으며 포함 파일 mkl_spblas.fi에서 MKL 설치 디렉토리 (예 :/path/to/mkl/include /)에 있습니다.

INTERFACE 
    subroutine mkl_ddnscsr (job, m, n, Adns, lda, Acsr, AJ, AI, info) 
    integer   job(8) 
    integer   m, n, lda, info 
    integer   AJ(*), AI(m+1) 
    double precision Adns(*), Acsr(*) 
    end 
END INTERFACE 

이 루틴은 포트란 스타일 더미 인수 (Adns(*) 같은 즉, 명시 적 모양의 배열 AI(m+1) 또는 가정 크기의 배열)을 가지고 있기 때문에, 당신은 어떤 로컬 또는 할당 가능한 배열 (후 발신자 측에서 할당)를 통과 할 수있다 실제 논증으로. 또한 인터페이스 블록을 명시 적으로 작성하지 않아도되지만 잠재적 인 인터페이스 불일치를 감지하려면 호출자 측의 include에게 유용해야합니다.

매뉴얼에 따르면, 그것은 (희소 행렬에 조밀 한 변환 루틴) mkl_ddnscsr처럼 보이는이 같은 작동합니다

program main 
    implicit none 
    ! include 'mkl_spblas.fi' !! or mkl.fi (not mandatory but recommended) 
    integer :: nzmax, nnz, job(8), m, n, lda, info, irow, k 
    double precision :: A(10, 20) 
    double precision, allocatable :: Asparse(:) 
    integer, allocatable :: ia(:), ja(:) 

    A(:, :) = 0.0d0 
    A(2, 3) = 23.0d0 
    A(2, 7) = 27.0d0 
    A(5, 4) = 54.0d0 
    A(9, 9) = 99.0d0 

    !! Give an estimate of the number of non-zeros. 
    nzmax = 10 

    !! Or assume that non-zeros occupy at most 2% of A(:,:), for example. 
    ! nzmax = size(A)/50 

    !! Or count the number of non-zeros directly. 
    ! nzmax = count(abs(A) > 0.0d0) 

    print *, "nzmax = ", nzmax 

    m = size(A, 1) !! number of rows 
    n = size(A, 2) !! number of columns 
    lda = m    !! leading dimension of A 

    allocate(Asparse(nzmax)) 
    allocate(ja(nzmax)) !! <-> columns(:) 
    allocate(ia(m + 1)) !! <-> rowIndex(:) 

    job(1) = 0  !! convert dense to sparse A 
    job(2:3) = 1  !! use 1-based indices 
    job(4) = 2  !! use the whole A as input 
    job(5) = nzmax !! maximum allowed number of non-zeros 
    job(6) = 1  !! generate Asparse, ia, and ja as output 

    call mkl_ddnscsr(job, m, n, A, lda, Asparse, ja, ia, info) 

    if (info /= 0) then 
     print *, "insufficient nzmax (stopped at ", info, "row)"; stop 
    endif 

    nnz = ia(m+1) - 1 
    print *, "number of non-zero elements = ", nnz 

    do irow = 1, m 
     !! This loop runs only for rows having nonzero elements. 
     do k = ia(irow), ia(irow + 1) - 1 
      print "(2i5, f15.8)", irow, ja(k), Asparse(k) 
     enddo 
    enddo 

end program 

ifort14와 (ifort -mkl test.f90로 컴파일합니다.0) 예상 결과를 nzmax의 판정에 대해서는

nzmax =   10 
number of non-zero elements =   4 
    2 3 23.00000000 
    2 7 27.00000000 
    5 4 54.00000000 
    9 9 99.00000000 

제공, I는 적어도 3 가지 방법이 거기 생각한다 : (1) 단의 추측 값 (상기와 같이)을 사용하여, (2) 전체 배열에서 0이 아닌 요소의 비율을 가정합니다. 또는 (3) 고밀도 어레이의 비 제로 수를 직접 계산하십시오. 어쨌든 정확한 nonzeros 수를 출력 (nnz)으로 가지고 있으므로 Asparseja을 정확한 크기 (필요한 경우)로 다시 할당 할 수 있습니다.

마찬가지로 또는 this (또는 this) 페이지에서 PARDISO의 인터페이스를 찾을 수 있습니다.

+0

이 페이지는 rowIndex (:)에 대한 추가 정보로 유용합니다 http://www.hpc.ut.ee/dokumendid/ips_xe_2015/composerxe/Documentation/en_US/mkl/mklman /GUID-9FCEB1C4-670D-4738-81D2-F378013412B0.htm – roygvib

+0

이것은 이제 작동하는 것 같습니다. 컴파일 오류가없고 코드가 실행됩니다. 하지만 계산 중간에 다음과 같은 오류 메시지가 나타납니다. 메시지 # 174 = 16 진수 000000ae 인 포트란 RTL 메시지 버퍼를 할당하기위한 메모리가 부족합니다. 내 코드는 PARDISO 솔버를 반복적으로 사용하여 미분 방정식 세트를 푸는데 사용됩니다. 나는 무엇이 잘못되었는지에 대한 아이디어가 부족합니다 ... – Charles

+0

흠 ... 이유에 대해 확실히 말할 수는 없지만이 페이지가 도움이 될까요? http://stackoverflow.com/questions/9751996/how-can-i-find-the-cause-for-a-memory-leak-in-fortran-2003-program 별도의 질문을하는 것이 유용 할 수 있습니다 (인텔 포럼). – roygvib