2016-10-11 6 views
1

lapack 및 blas를 C++ 코드에 사용해야하므로 Linux 시스템에서 MKL, ACML 또는 기본 lapack 및 blas를 연결하려고합니다. 불행히도, 그들은 c에서 다른 관습을 가지고 있습니다. 예를 들어, MKL (mkl_blas.h)에서 zdotc이lapack 및 blas를 C++로 호출하십시오.

zdotc(&result, &n, x, &incx, y, &incy); 

및 기본 LAPACK 및 BLAS에서 (FORTRAN 버전) zdotc 전화입니다 :

result = zdotc_(&n, x, &incx, y, &incy); 

내 코드 중 하나 MKL을 사용하려면, ACML, 또는 기본 lapack blas. 나는 이것에 대한 랩을 쓸 필요가 :

#ifdef FORTRAN_NO_UNDERSCORE 
    #define F77NAME(x) x 
#else 
    #define F77NAME(x) x##_ 
#endif 

complex<double> zdotc_wrap(int n, const complex<double>*x, int incx, const complex<double>*y, int incy) 
{ 
    #if defined(USE_MKL) 
    complex<double> result; 
    zdotc(&result, &n, x, &incx, y, &incy) 
    return result; 
    #elif defined(USE_LAPACK_BLAS) 
    return F77NAME(zdotc)(&n, x, &incx, y, &incy); 
    #elif defined(USE_ACML) 
    ... 
    #endif 
} 

많은 기능이 있지만, 그들 각각에 대해 랩을 작성하는 시간을 요한다. 나는 그들 만의 고유 한 협약이 있기를 희망한다. 코드에서 lapack 및 blas를 사용하는 경우 어떻게이 문제를 해결할 수 있습니까? 당신은 모든 기능을 감싸고 있습니까? 랩이 있으면 나와 공유 할 수 있다면 좋을 것입니다.


업데이트 :

complex<double> result; 
#ifndef FORTRAN_COMPLEX_FUNCTIONS_RETURN_VOID 
result = zdotc(
#else 
zdotc(&result, 
#endif 
&n, x, &incx, y, &incy); 

어떤 제안 :

#ifndef FORTRAN_COMPLEX_FUNCTIONS_RETURN_VOID 
extern complex<double> zdotc(
#else 
extern void zdotc(complex<double>* retval, 
#endif 
    const int *n, 
    const complex<double> *zx, 
    const int *incx, 
    const complex<double> *zy, 
    const int *incy 
); 

가 그럼 난으로이 함수를 호출 할 수 있습니다 :

내가이 문제를 해결하는 하나의 방법을 찾을? 더 나은 솔루션? 도와 줘서 고마워.

답변

1

공급 업체가 제공하는 BLAS 및 LAPACK 구현에는 보통 Fortran 77 컴파일러가 원래 어떻게 작동했는지를 나타내는 밑줄이있는 기호가 포함됩니다. 최신 gfortran 동작은 호환성을 위해 밑줄을 추가하는 것이지만 -fno-underscoringoption이 해제됩니다.

참조 BLAS 및 LAPACK과 같은 gfortran을 사용하여 직접 컴파일하는 코드의 경우 복잡한 값을 직접 반환할지 또는 간접 result 포인터 인수를 사용할지 여부를 선택할 수 있습니다. 간접적 인 동작을 얻으려면 -ff2c으로 컴파일하십시오. 기본 gfortran 동작은 복잡한 값을 직접 반환하는 것입니다.

코드에서 매크로 및 줄 바꿈을 피하는 가장 간단한 방법은 추가 된 첫 번째 인수에서 복잡한 결과의 이름과 간접 반환 값에 후행 밑줄을 사용하는 것입니다. 이는 공급 업체 라이브러리와 호환 될 것입니다. 그런 다음 BLAS와 LAPACK을 -ff2c으로 컴파일하여 거기서 작동하게하십시오.

유연성을 극대화하기 위해 랩 기능을 사용할 수 있습니다. 래퍼에서는 복잡한 인수가 직접 반환되는지 아닌지에 대해 걱정할 필요가 있습니다. 각기 다른 라이브러리에 대해 특별한 처리가 필요하지 않아야합니다. CDOTU CDOTC ZDOTU ZDOTC : BLAS에서

complex<double> zdotc_wrap(int n, const complex<double>*x, int incx, const complex<double>*y, int incy) 
{ 
    #if defined(FORTRAN_COMPLEX_FUNCTIONS_RETURN_VOID) 
    complex<double> result; 
    zdotc_(&result, &n, x, &incx, y, &incy); 
    return result; 
    #else 
    return zdotc_(&n, x, &incx, y, &incy); 
    #endif 
} 

는 포장 할 필요가 기능의 소수에 불과하다.LAPACK에는 단지 CLADIV ZLADIV (나는 생각합니다)이 있습니다.

+0

감사합니다. 이것은 매우 유용합니다. BLAS와 LAPACK을'-ff2c'로 컴파일하면 문제를 해결할 수 있습니다. 제가 도서관을 쓰는 동안 다른 사람들이 저의 도서관을 융통성있게 사용할 수 있기를 바랍니다. BLAS를 다시 컴파일하고 LAPACK은 간접 비트입니다. 정의를 추가하여이 문제를 해결하기 위해 노력하고 있습니다, 그것은 내 질문에 업데이트됩니다. 의견 있으십니까? –

+0

내 대답이 업데이트되었습니다. –

+0

고마워요. 제가 원래하고있는 일입니다. 나는 지금 더 좋은 방법이 없다고 생각합니다. –

0

내 C++ 코드에서 lapack을 사용하고 있는데 그 문제가 없었습니다. cosmo++ 라이브러리를 확인할 수 있습니다. source/matrix_impl.cpp 파일을보십시오. 나는 _으로 끝나는 필요한 기능을 포함하는 extern "C" 블록을 가지고있다. 나는 lapack/blas와 MKL에 대해이 코드를 아무런 문제없이 컴파일했다. 나는 gcc와 인텔 컴파일러를 사용했다. 그것은 또한 framework Accelerate와 내 맥에서 컴파일합니다.

+0

감사합니다. dgemm, dgetrf 및 dgetri의 경우이 세 라이브러리의 규칙은 동일합니다. zdotc 유형의 기능은 다른 기능입니다. –

+0

나는 본다. 매크로를 사용해야합니다. 함수 이름에 매크로 래퍼를 정의하는 것은 무엇입니까? 즉, 이름에 _ 또는 _을 추가하거나 추가하지 않는 매크로가 있습니까? 그렇게하면 모든 단일 기능에 대해 매크로를 작성할 필요가 없습니다. – grigor

+0

나는 이미 게시물에서'#define F77NAME (x) x ## _'매크로를 사용하고 있습니다. 문제는'zdotc'가 MKL과 기본 blas에서 다른 인수를 허용한다는 것입니다. –