![]() |
Blitz Support : |
From: Julian Cummings (cummings_at_[hidden])
Date: 2004-06-11 15:06:48
Hi Carlos,
I am still not clear on how you are invoking your testWrapper function
template. When you have an array of complex values, do you pass a
std::complex<float>* or a MKL_Complex8* as the first argument to
testWrapper? Also, do you specify the template argument, or do you
assume that the compiler should be able to deduce this? If you pass a
MKL_Complex8* as the first argument to testWrapper, I do not believe
that the compiler can automatically deduce that the template argument
should be std::complex<float>, since T=MKL_Complex8 would produce the
same exported type mType. If instead you pass a std::complex<float>*,
it will not be automatically converted to a MKL_Complex8*, so you have
to explicitly cast the pointer to the proper type.
I can see the value of using the MKL_Traits struct to allow a general
representation of your matrix decomposition class, but I don't think the
function template testWrapper adds any value here, since it has to be
fully specialized anyway. Using a non-templated overloaded wrapper
function just seems simpler to me in this case, and there should be no
difference in terms of function inlining. By the way, there is an error
in your code for testWrapper below. The typename keyword should not be
used in the specializations of the testWrapper function template, only
in the general template.
Regards, Julian C.
carlos.rega_at_[hidden] wrote:
>
> Hi Julian, thanks for your reply
>
> The code I have trouble with is something like this:
>
> using namespace std;
>
> template<class T> struct MKL_Traits {
> typedef T mType;
> typedef T mPrec;
> };
>
> template<> struct MKL_Traits<complex<float> > {
> typedef MKL_Complex8 mType;
> typedef float mPrec;
> };
>
> void sTest(float*,int*);
> void cTest(MKL_Complex8*,int*);
>
> template<class T> void testWrapper(typename MKL_Traits<T>::mType *,int
> *);
>
> template<> void testWrapper<float>(typename MKL_Traits<float>::mType
> *m,int *info)
> {
> sTest(m,info);
> }
>
> template<> void testWrapper<complex<float> >(typename
> MKL_Traits<complex<float> >::mType *m,int *info)
> {
> cTest(m,info);
> }
>
>
> compiles fine with g++, but visual studio says that the explicit
> specialisation is not an specialisation of a function template. It is
> not really a problem, as overloading does it. I was trying to use
> templates as I expect these to get inlined no matter what, while the
> overloaded functions may or may not get inlined depending on the
> optimisation options, am I correct in this assumption?
>
> The traits comes into play in some LAPACK functions that mix real and
> complex types. For instance, singular value decomposition, the
> singular values are real, but the matrices are complex, so the
> SVDecomposition class is something like:
>
> template <class T> class SVDecomposition {
> public:
> /// default constructor
> CSVDecomposition(void):mSingularValues(Array<typename
> MKL_Traits<T>::mPrec,1>(FortranArray<1>())),mU(Array<T,2>(FortranArray<2>())),mVT(Array<T,2>(FortranArray<2>())){;}
>
> /// perform the transformation
> virtual void DoTransform(const Array<T,2>&);
> /// return the matrix U (left singular vectors)
> Array<T,2> U(void){return mU;}
> /// return the transpose of V (right singular vectors)
> Array<T,2> VT(void){return mVT;}
> /// return the singular values of the matrix
> Array<typename MKL_Traits<T>::mPrec,1> SingularValues(void){return
> mSingularValues;}
> private:
> /// contains the singular values
> Array<typename MKL_Traits<T>::mPrec,1> mSingularValues;
> /// contains U
> Array<T,2> mU;
> /// contains VT
> Array<T,2> mVT;
> };
>
> that way for float both the singular values and the matrices are
> float, but for complex<float> the singular values are float and the
> matrices are complex<float>, so I avoid having to specialise
> SVDecomposition for the complex types explicitly. Also, it should help
> if the representation for complex in LAPACK changed, in that case only
> the traits struct needs to be changed, and the rest of the code is
> independent of the particular representation LAPACK uses (so long as
> the pointers can be casted to and fro).
>
> Am I doing things too complicated unnecessarily?
>
> Regards
>
> Carlos A. Rega, PhD
> Development Scientist
> Malvern Instruments Ltd
> Grovewood Rd, Malvern
> WR14 1XZ
>
> Tel: +44 (0)1684 581 304
> Fax: +44 (0)1684 892 789
>
> e-mail: carlos.rega_at_[hidden]
>
>
>
> "Julian C. Cummings" <cummings_at_[hidden]>
> Sent by: blitz-support-bounces_at_[hidden]
>
> 10/06/2004 21:40
> Please respond to cummings; Please respond to Support list for Blitz++
>
>
> To: "'Support list for Blitz++'"
> <blitz-support_at_[hidden]>
> cc:
> Subject: RE: [Blitz-support] Template support in VC++ .NET
>
>
>
>
> Hello Carlos,
>
> I would need to see the precise code being compiled to offer more specific
> comments. However, just looking over the code snippets below, I am
> puzzled
> by this one:
>
> > template<class T>
> > void lapack_function_wrapper(MKL_Traits<T>::Type *,MKL_Traits<T>::Type
> *,int*)
>
> Why would you template the wrapper function on the exported types from the
> MKL_Traits class rather than templating on the initial type T and then
> converting types inside the wrapper function specializations? How is this
> any better than simple overloading?
>
> void lapack_function_wrapper(float *x, float *y, int *z) {
> return slapack_function(x,y,z);
> }
> void lapack_function_wrapper(double *x, double *y, int *z) {
> return dlapack_function(x,y,z);
> }
> void lapack_function_wrapper(std::complex<float> *x,
> std::complex<float> *y,
> int *z) {
> return clapack_function(reinterpret_cast<MKL_Complex8 *>(x),
> reinterpret_cast<MKL_Complex8 *>(y), z);
> }
> void lapack_function_wrapper(std::complex<double> *x, std::complex<double>
> *y, int *z) {
> return zlapack_function(reinterpret_cast<MKL_Complex16 *>(x),
> reinterpret_cast<MKL_Complex16 *>(y), z);
> }
>
> Since you are specializing the wrapper function, there is no real need to
> utilize the MKL_Traits class here, as the result type is already known.
> Maybe I am missing something here? A complete example of the code that
> fails to compile under VS.NET would help clarify the problem you are
> having.
> I tried to cook up my own example using template specialization, but I
> don't
> encounter any similar compilation problems with VS.NET.
>
> Regards, Julian C.
>
> Dr. Julian C. Cummings
> Staff Scientist, CACR/Caltech
> (626) 395-2543
> cummings_at_[hidden]
>
>
> > -----Original Message-----
> > From: blitz-support-bounces_at_[hidden]
> > [mailto:blitz-support-bounces_at_[hidden]] On Behalf Of
> > carlos.rega_at_[hidden]
> > Sent: Thursday, June 10, 2004 2:52 AM
> > To: Support list for Blitz++
> > Subject: [Blitz-support] Template support in VC++ .NET
> >
> >
> >
> > Hi,
> >
> > Just had a quick look about the exporting makefiles issue in
> > the VC++ help, and the 2003 version explicitly says that you
> > can not export makefiles (whatever the reason for that may
> > be). However, there seems to be the possibility of running
> > the editor, would you believe it, in a command line mode that
> > will treat the solution file as a makefile. Whatever was
> > wrong with exporting makefiles and running them through nmake
> > does not explain.
> >
> > Anyhow, now that I am in rant mode about Visual Studio I will
> > comment on a problem I have found. As I said in a previous
> > message we are trying to write a wrapper that uses blitz and
> > the intel MKL implementation of LAPACK. In general it is
> > rather simple, just passing the pointers returned by the
> > data() method to the LAPACK functions.
> >
> > I started writing my code using gcc, just to check that the
> > project was feasible and would not take a huge amount of
> > time. Using gcc I used the following approach to wrap the
> > LAPACK functions. For each function there are usually 4
> > flavours, two real (single and double precision) and two
> > complex (again single and double). The signature of the
> > function is the same, only the types of the arguments are different:
> >
> > slapack_function(float *,float*,int*) // single precision real
> > dlapack_function(double*,double*,int*) // double precision real
> > clapack_function(MKL_Complex8*,MKL_Complex8*,int*) // single
> > precision complex
> > zlapack_function(MKL_Complex16*,MKL_Complex16*,int*) //
> > double precision complex
> >
> > the MKL_Complex types are structs like:
> >
> > struct MKL_Complex8 {
> > float real;
> > float imag;
> > };
> >
> > so you can cast safely from complex<float>* to MKL_Complex8*
> > and the other way around.
> >
> > The C++ interface will be a set of classes that call MKL as a
> > back-end, and use blitz for the matrix representation, like so:
> >
> > template<class T> class LUFactorisation
> > {
> >
> > public:
> >
> > /// default constructor
> >
> >
> > CLUFactorisation(void):mResult(Array<T,2>(FortranArray<2>())),
> > mIpiv(Array<int,1>(FortranArray<1>())){;}
> >
> > /// implements the call to the LAPACK function
> >
> > void Factor(const Array<T,2>&);
> >
> > /// returns the L matrix
> >
> > Array<T,2> L(void);
> >
> > /// returns the U matrix
> >
> > Array<T,2> U(void);
> >
> > private:
> >
> > Array<T,2> mResult;
> >
> > /// contains the permutation vector, row i is swapped
> > with row mIpiv(i)
> >
> > Array<int,1> mIpiv;
> >
> > };
> >
> > There are two possibilities for getting Factor to call the
> > right LAPACK function, explicit specialisation of the
> > template for each type, or writing a template function that
> > wraps the LAPACK function and let the compiler generate the
> > four different Factor functions. The second approach is more
> > economical, as in this case the only difference between the
> > four template specialisations is which function to call, and
> > the rest of the code is exactly the same.
> >
> > So, I would write something like:
> >
> > template<class T> void
> > lapack_function_wapper(MKL_Traits<T>::Type
> > *,MKL_Traits<T>::Type *,int*)
> >
> > and specialise for each type. Here MKL_Traits<T>::Type
> > returns the correct type expected by the MKL functions, float
> > for T = float, double for T=double, MKL_Complex8 for
> > complex<float> and MKL_Complex16 for complex<double>.
> >
> > This worked fine with gcc, with these wrappers getting
> > expanded in line, even without optimisation.
> >
> > Now, here it is a VS only shop, so I need to port that code
> > to VS, luckily VS .NET 2003 compiles blitz, so it should be a
> > matter of just copying the files and generating the project,
> > as there is nothing really fancy in what I have written,
> > right? Nope, The above template trick will not work in VS, it
> > refuses to recognise the specialisations as specialisations
> > of the above template, and I end up with no other choice but
> > to use overloading instead. Not that overloading is all that
> > bad, but I would expect that templates would give slightly
> > better performance, as they should get automatically inlined
> > at compile time, while it might be slightly trickier to get
> > the compiler to inline the overloaded functions.
> >
> > So, my question is, is what I am trying to do non standard
> > and it just happens that it works in gcc, but it is not
> > really supposed to or is VS support of templates still
> > slightly flaky?
> >
> > Thanks for your patience
> >
> > Carlos A. Rega, PhD
> > Development Scientist
> > Malvern Instruments Ltd
> > Grovewood Rd, Malvern
> > WR14 1XZ
> >
> > Tel: +44 (0)1684 581 304
> > Fax: +44 (0)1684 892 789
> >
> > e-mail: carlos.rega_at_[hidden]
> >
> > --------------------------------------------------------------
> > ------------------------------------------------------
> > This email and any files transmitted with it are confidential
> > and intended solely for the use of the individual or entity
> > to whom they are addressed.
> >
> > If you have received this email in error please notify the
> > originator of the message.
> >
> > Any views expressed in this message are those of the
> > individual sender, except where the sender specifies and with
> > authority, states them to be the views of Malvern Instruments.
> >
> >
>
>
> _______________________________________________
> Blitz-support mailing list
> Blitz-support_at_[hidden]
> http://www.oonumerics.org/mailman/listinfo.cgi/blitz-support
>
>
>
>
>
> --------------------------------------------------------------------------------------------------------------------
> This email and any files transmitted with it are confidential and
> intended solely for the use of the individual or entity to whom
> they are addressed.
>
> If you have received this email in error please notify the
> originator of the message.
>
> Any views expressed in this message are those of the individual
> sender, except where the sender specifies and with authority,
> states them to be the views of Malvern Instruments.
-- Dr. Julian C. Cummings E-mail: cummings_at_[hidden] California Institute of Technology Phone: 626-395-2543 1200 E. California Blvd., Mail Code 158-79 Fax: 626-584-5917 Pasadena, CA 91125