2017-03-01 10 views
2

병렬 MPI 포트란 프로그램을 MPI를 사용하는 병렬 C 라이브러리에도 연결하려고합니다. 소프트웨어 아키텍처는 Fortran 중심이므로 Fortran 측에서 가능한 한 많이 유지하려고합니다.iso_c_binding을 사용하여 포트란에서 C로 MPI 커뮤니케이터 핸들을 전달하는 방법

그래서 C 루틴에 MPI 커뮤니케이터 핸들을 전달해야합니다. 그들은

int CFunction(int *something, MPI_Comm *Ccomm) 

MPI는 C 커뮤니케이터 핸들에 포트란을 번역하는 인터페이스와 함께 제공되는 형식은 다음과 같습니다 그러나

MPI_Comm MPI_Comm_f2c(MPI_Fint comm) 

,이 루틴은 그래서 지금 내가했습니다 C에서 호출 할 가정된다 I가 포트란 의사 소통을 전달할 수 있습니다 C 래퍼 기능을 추가했다 : 나는 할 수 있도록 포트란의 C 바인딩을 사용하여 - - CFunction_FMPI

int CFunction_FMPI(int *something, MPI_Fint *Fcomm) 
{ MPI_Comm Ccomm; int status; 
    Ccomm = MPI_Comm_f2c(*Fcomm); // Convert Fortran->C communicator 
    status = CFunction(*something,*Ccomm); // Call original function 
    return status; 
} 

은 내가 제 2의 인터페이스를 작성했다 Fortran에서 전화해야합니다.

제 질문은 포트란 -> C 커뮤니케이터 변환으로 C 래퍼를 피하는 더 좋은 방법이 아닙니까? 나는 MPI_Comm_f2c을 Fortran에서 직접 호출하고 결과를 type(c_ptr) 또는 integer(c_int) 변수로 저장하는 것이 가장 좋을 것이라고 생각하지만, MPI_Comm 유형과 Fortran 사이에 직접적/일반적인 바인딩이 없기 때문에이를 수행하지 못했습니다.

답변

2

아니요, 더 좋은 방법이 있다고 생각하지 않습니다. 그리고 제가 걱정할 정도로 복잡하지는 않습니다. 당신은 당신의 CFunction_FMPI 반대 방향이며, 단지 의사 소통을 변환

https://github.com/LadaF/PoisFFT/blob/master/src/f_mpi_comm_c2f.c

에서 내가 사용하는 비슷한 기능을 볼 수 있습니다. C에서 포트란까지입니다.

// This function is callable from Fortran. MPI_Comm_c2f itself may be just a macro. 

MPI_Fint f_MPI_Comm_c2f(MPI_Comm *comm) { 
    return MPI_Comm_c2f(*comm); 
} 

는 그것은보다

interface 
    integer function MPI_Comm_c2f(c_handle) bind(C, name="f_MPI_Comm_c2f") 
     use iso_c_binding 
     type(c_ptr), value :: c_handle 
    end function 
end interface 

로 포트란에서 호출 중요한 점은 당신이 정말로 포트란에서 호출 할 수 있도록 일부 MPI가하는 C 매크로가 아닌 기능을 도서관에 MPI_Comm_c2f임을이다. MPI_Comm_f2c도 매크로가 될 수 있으므로 포트란에서 호출 할 수는 없습니다. 당신이 할 수있는 일


MPI_Comm_f2c의 C 래퍼를 호출하는 포트란 기능을 작성하고보다 것은

status = CFunction(something, c_comm) 

bind(C) 인터페이스를 사용하여 포트란에서 C 함수를 호출함으로써 생성 방지하는 것입니다 각 C 함수에 대한 랩퍼. 포트란 인터페이스 블록 만 있으면됩니다.

Fortran *에 MPI_Comm (실제로는 포인터 또는 int)이 없으므로 불투명 포인터를 사용해야합니다.

MPI_Comm* f_MPI_Comm_f2c(MPI_Fint Fcomm) 
{ MPI_Comm* Ccomm; 
    Ccomm = malloc(sizeof(MPI_Comm)); 
    *Ccomm = MPI_Comm_f2c(Fcomm); 
    return Ccomm; 
} 

불투명 포인터 type(c_ptr)을 반환합니다. (잠재적 인 C 코딩 오류를 확인하기 위해 세미콜론을 사용하는 것을 잊어 버렸다.)

포트란 커뮤니케이터를 C 커뮤니 케이터의 포인터로 변환하는 것보다 훨씬 간단합니다.

type(c_ptr) :: c_comm 
c_comm = f_MPI_Comm_f2c(comm) 

*이 MPI-3 파생 형 type(MPI_Comm)가 있지만, 어쨌든 변환 루틴으로 변환되어야 정수 구성 요소를 포함한다.

+0

감사합니다. @ vladimir-f, 귀하의 접근 방식은 매우 잘 작동합니다. 사실, 코드에서'f_MPI_Comm_f2c' 함수를 한 번만 호출하면 C 포인터의 지루한 할당/할당 해제를 피할 수 있습니다. Fortran이 C++과 같은 MPI의 객체 지향 캡슐화를 제공하면 좋을 것입니다 ... –

+0

사실 C++ MPI 바인딩은 더 이상 사용되지 않습니다. 현대 Fortran 2008 바인딩은 꽤 좋은 단계입니다. –

+0

그래도 MPI 구현의 .mod 파일 사용은 항상 컴파일러에 종속적일까요? .mod 형식은 해당 C 헤더가 –