2016-10-11 3 views
1

私のC++コードでlapackとblasを使う必要があります.MKL、ACML、またはデフォルトのlapackとblasをLinuxシステムにリンクしたいと思っています。残念なことに、彼らは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を使用している場合、どのようにこの問題を解決しますか?あなたはすべての機能のラップを持っていますか?ラップがあれば、それを私と分かち合うことができれば素晴らしいだろう。


更新:

私はこの問題を解決する1つの方法を見つける:

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をでコンパイルして動作させます。

柔軟性を最大限に高めるために、折り返し機能を使用できます。ラッパーの中では、複雑な引数が直接返されるかどうかについて心配する必要があります。異なるライブラリごとに特別な処理をする必要はありません。 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

ありがとうございます。これは非常に便利です。 '-ff2c'でBLASとLAPACKをコンパイルすることで、問題を解決できます。私は図書館を書いている間、他の人々が私の図書館を柔軟に利用できるように願っています。 BLASを再コンパイルし、LAPACKはビットを間接的に点灯します。私は定義を追加することによってこの問題を解決しようとしています、それは私の質問で更新されます。何か提案はありますか? –

+0

私の答えを更新しました。 –

+0

ありがとう、これは私が元々やっていることです。今はもっと良い方法はないと思う。 –

0

私はC++コードでlapackを使用していますが、その問題はありませんでした。 cosmo++ライブラリを確認できます。 source/matrix_impl.cppファイルを見てください。私にはextern "C"というブロックがあり、必要な機能があり、最後に_で終わります。私はlapack/blasとMKLに対してこのコードを問題なくコンパイルしました。私はgccとintelコンパイラを使用しています。また、framework Accelerateと私のMacでコンパイルします。

+0

ありがとうございます。 dgemm、dgetrf、およびdgetriの場合、これらの3つのライブラリーには同じ規則があります。 zdotcタイプの機能の場合、それらは異なっています。 –

+0

私は参照してください。マクロを使う必要があると思います。関数名のマクロラッパーを定義するのはどうでしょうか?つまり、名前に '_'を追加したり追加したりしないマクロを持つのはどうですか?そうすれば、マクロごとに関数を記述する必要はありません。 – grigor

+0

私は既に投稿でマクロを使用しています、 '#define F77NAME(x)x ## _'。問題は、 'zdotc'がMKLとデフォルトのblasで異なる引数を受け入れることです。 –

関連する問題