fflas-ffpack icon indicating copy to clipboard operation
fflas-ffpack copied to clipboard

FFLAS::fgemm does not compile with Givaro::GFqDom

Open gmh33 opened this issue 7 years ago • 3 comments

The following bit of code does not compile. LinBox::BlasMatrixDomain.mul calls FLAS::fgemm. I'm building in the linbox test directory and added the file to the Makefile.am

#include "linbox/linbox-config.h"

#include <iostream>

#include "givaro/givtimer.h"

#include "linbox/ring/modular.h"
#include "linbox/matrix/matrix-domain.h"
#include "linbox/matrix/random-matrix.h"

using namespace LinBox;

typedef Givaro::GFqDom<int64_t> Field;
typedef typename Field::RandIter RandIter;
typedef BlasMatrixDomain<Field> MatrixDom;
typedef BlasMatrix<Field> Matrix;

int main() {
	size_t p = 3, e = 13;
	
	Field F(p, e);
	MatrixDom MD(F);
	
	Matrix A(F, 5, 5);
	Matrix B(F, 5, 5);
	Matrix C(F, 5, 5);
	
	RandIter RI(F);
	RandomDenseMatrix<RandIter, Field> RDM(F, RI);
	
	RDM.random(A);
	RDM.random(B);
	
	MD.mul(C, A, B);
	
	A.write(std::cout) << std::endl;
	B.write(std::cout) << std::endl;
	std::cout << "==" << std::endl;
	C.write(std::cout) << std::endl;
	
	return 0;
}

Compiling results in the following output:

g++ -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mavx -mavx2 -DLinBoxTestOnly -O2 -Wall -g -DNDEBUG -U_LB_DEBUG -g -DNDEBUG -U_LB_DEBUG -I.. -fopenmp -fabi-version=6 -I/home/gavin/opt/givaro/include -I/home/gavin/opt/fflas-ffpack/include        -DLinBoxTestOnly -O2 -Wall -g -DNDEBUG -U_LB_DEBUG -g -DNDEBUG -U_LB_DEBUG -I.. -fopenmp -fabi-version=6 -I/home/gavin/opt/givaro/include -I/home/gavin/opt/fflas-ffpack/include      test-fgemm.C -o test-fgemm -lntl      -L/home/gavin/opt/givaro/lib -fopenmp -llapack -lblas -lgivaro -lgmp -lgmpxx  
In file included from /home/gavin/opt/fflas-ffpack/include/fflas-ffpack/fflas/fflas_fgemm.inl:445:0,
                 from /home/gavin/opt/fflas-ffpack/include/fflas-ffpack/fflas/fflas.h:109,
                 from /home/gavin/opt/fflas-ffpack/include/fflas-ffpack/ffpack/ffpack.h:47,
                 from ../linbox/matrix/matrixdomain/blas-matrix-domain.h:45,
                 from ../linbox/matrix/matrix-domain.h:68,
                 from test-fgemm.C:8:
/home/gavin/opt/fflas-ffpack/include/fflas-ffpack/fflas/fflas_fgemm/fgemm_winograd.inl: In instantiation of ‘typename Field::Element_ptr FFLAS::fgemm(const Field&, FFLAS::FFLAS_TRANSPOSE, FFLAS::FFLAS_TRANSPOSE, size_t, size_t, size_t, typename Field::Element, typename Field::ConstElement_ptr, size_t, typename Field::ConstElement_ptr, size_t, typename Field::Element, typename Field::Element_ptr, size_t, FFLAS::MMHelper<Field, FFLAS::MMHelperAlgo::Winograd, FieldTrait>&) [with Field = Givaro::GFqDom<long int>; ModeT = FFLAS::ModeCategories::DefaultTag; typename Field::Element_ptr = long int*; size_t = long unsigned int; typename Field::Element = long int; typename Field::ConstElement_ptr = const long int*]’:
/home/gavin/opt/fflas-ffpack/include/fflas-ffpack/fflas/fflas_fgemm.inl:369:15:   required from ‘typename Field::Element_ptr FFLAS::fgemm(const Field&, FFLAS::FFLAS_TRANSPOSE, FFLAS::FFLAS_TRANSPOSE, size_t, size_t, size_t, typename Field::Element, typename Field::ConstElement_ptr, size_t, typename Field::ConstElement_ptr, size_t, typename Field::Element, typename Field::Element_ptr, size_t, FFLAS::MMHelper<Field, FFLAS::MMHelperAlgo::Auto, ModeT, ParSeq>&) [with Field = Givaro::GFqDom<long int>; ModeT = FFLAS::ModeCategories::DefaultTag; ParSeq = FFLAS::ParSeqHelper::Sequential; typename Field::Element_ptr = long int*; size_t = long unsigned int; typename Field::Element = long int; typename Field::ConstElement_ptr = const long int*]’
/home/gavin/opt/fflas-ffpack/include/fflas-ffpack/fflas/fflas_fgemm.inl:304:17:   required from ‘typename Field::Element_ptr FFLAS::fgemm(const Field&, FFLAS::FFLAS_TRANSPOSE, FFLAS::FFLAS_TRANSPOSE, size_t, size_t, size_t, typename Field::Element, typename Field::ConstElement_ptr, size_t, typename Field::ConstElement_ptr, size_t, typename Field::Element, typename Field::Element_ptr, size_t, FFLAS::ParSeqHelper::Sequential) [with Field = Givaro::GFqDom<long int>; typename Field::Element_ptr = long int*; size_t = long unsigned int; typename Field::Element = long int; typename Field::ConstElement_ptr = const long int*]’
/home/gavin/opt/fflas-ffpack/include/fflas-ffpack/fflas/fflas_fgemm.inl:348:8:   required from ‘typename Field::Element_ptr FFLAS::fgemm(const Field&, FFLAS::FFLAS_TRANSPOSE, FFLAS::FFLAS_TRANSPOSE, size_t, size_t, size_t, typename Field::Element, typename Field::ConstElement_ptr, size_t, typename Field::ConstElement_ptr, size_t, typename Field::Element, typename Field::Element_ptr, size_t) [with Field = Givaro::GFqDom<long int>; typename Field::Element_ptr = long int*; size_t = long unsigned int; typename Field::Element = long int; typename Field::ConstElement_ptr = const long int*]’
../linbox/matrix/matrixdomain/blas-matrix-domain.inl:431:16:   required from ‘Matrix1& LinBox::BlasMatrixDomainMulAdd<Operand1, Operand2, Operand3>::operator()(const typename Matrix1::Field::Element&, Matrix1&, const typename Matrix1::Field::Element&, const Matrix2&, const Matrix3&) const [with Matrix1 = LinBox::BlasMatrix<Givaro::GFqDom<long int> >; Matrix2 = LinBox::BlasMatrix<Givaro::GFqDom<long int> >; Matrix3 = LinBox::BlasMatrix<Givaro::GFqDom<long int> >; typename Matrix1::Field::Element = long int]’
../linbox/matrix/matrixdomain/blas-matrix-domain.h:161:94:   required from ‘Operand1& LinBox::BlasMatrixDomainMul<Field, Operand1, Operand2, Operand3>::operator()(const Field&, Operand1&, const Operand2&, const Operand3&) const [with Field = Givaro::GFqDom<long int>; Operand1 = LinBox::BlasMatrix<Givaro::GFqDom<long int> >; Operand2 = LinBox::BlasMatrix<Givaro::GFqDom<long int> >; Operand3 = LinBox::BlasMatrix<Givaro::GFqDom<long int> >]’
../linbox/matrix/matrixdomain/blas-matrix-domain.h:444:66:   required from ‘Operand1& LinBox::BlasMatrixDomain<Field_>::mul(Operand1&, const Operand2&, const Operand3&) const [with Operand1 = LinBox::BlasMatrix<Givaro::GFqDom<long int> >; Operand2 = LinBox::BlasMatrix<Givaro::GFqDom<long int> >; Operand3 = LinBox::BlasMatrix<Givaro::GFqDom<long int> >; Field_ = Givaro::GFqDom<long int>]’
test-fgemm.C:34:16:   required from here
/home/gavin/opt/fflas-ffpack/include/fflas-ffpack/fflas/fflas_fgemm/fgemm_winograd.inl:405:6: error: ‘struct FFLAS::MMHelper<Givaro::GFqDom<long int>, FFLAS::MMHelperAlgo::Winograd, FFLAS::ModeCategories::DefaultTag, FFLAS::ParSeqHelper::Sequential>’ has no member named ‘Outmax’
    H.Outmax = HC.Outmax;
    ~~^~~~~~
/home/gavin/opt/fflas-ffpack/include/fflas-ffpack/fflas/fflas_fgemm/fgemm_winograd.inl:405:18: error: ‘struct FFLAS::MMHelper<Givaro::GFqDom<long int>, FFLAS::MMHelperAlgo::Classic, FFLAS::ModeCategories::DefaultTag, FFLAS::ParSeqHelper::Sequential>’ has no member named ‘Outmax’
    H.Outmax = HC.Outmax;
               ~~~^~~~~~
/home/gavin/opt/fflas-ffpack/include/fflas-ffpack/fflas/fflas_fgemm/fgemm_winograd.inl:406:6: error: ‘struct FFLAS::MMHelper<Givaro::GFqDom<long int>, FFLAS::MMHelperAlgo::Winograd, FFLAS::ModeCategories::DefaultTag, FFLAS::ParSeqHelper::Sequential>’ has no member named ‘Outmin’
    H.Outmin = HC.Outmin;
    ~~^~~~~~
/home/gavin/opt/fflas-ffpack/include/fflas-ffpack/fflas/fflas_fgemm/fgemm_winograd.inl:406:18: error: ‘struct FFLAS::MMHelper<Givaro::GFqDom<long int>, FFLAS::MMHelperAlgo::Classic, FFLAS::ModeCategories::DefaultTag, FFLAS::ParSeqHelper::Sequential>’ has no member named ‘Outmin’
    H.Outmin = HC.Outmin;
               ~~~^~~~~~
/home/gavin/opt/fflas-ffpack/include/fflas-ffpack/fflas/fflas_fgemm/fgemm_winograd.inl:411:91: error: no type named ‘DelayedField’ in ‘struct FFLAS::MMHelper<Givaro::GFqDom<long int>, FFLAS::MMHelperAlgo::Winograd, FFLAS::ModeCategories::DefaultTag, FFLAS::ParSeqHelper::Sequential>’
 e  MMHelper<Field, MMHelperAlgo::Winograd, ModeT>::DelayedField::Element DFElt;
                                                                          ^~~~~
Makefile:3039: recipe for target 'test-fgemm' failed
make: *** [test-fgemm] Error 1

gmh33 avatar Feb 26 '18 00:02 gmh33

Making GFqDom extend FiniteRing and adding the following snippet to fflas-ffpack/field/field-traits.h allows it compile, but I'm not sure whether or not it makes sense semantically.

template <typename Element> 
struct ModeTraits<Givaro::GFqDom<Element> >{typedef typename ModeCategories::DelayedTag value;};

template <> struct ModeTraits<Givaro::GFqDom<int64_t> >{typedef typename ModeCategories::ConvertTo<ElementCategories::MachineFloatTag> value;};

gmh33 avatar Feb 26 '18 03:02 gmh33

Hi, Several comments regarding the use of GFqDom in fflas-ffpack:

  • GFqDom has maxCardinality set to 65536, hence whenever it represents a prime field (e=1), then it can safely be converted to ModularBalanced or even ModularBalanced when the cardinality is small enough. So your proposed specilalization for ModeTraits<GFqDom<int64_t> > should not be restricted to Element=int64_t. However, this ModeTraits is determined at compile time where we can not test e==1 and the conversion to ModularBalanced<double> would then be erroneous whenever e>1. In such a case the ModeTrait should be set to GenericTag
  • If you are willing to use an extension field using Zech log tables and the ability to convert to double representations to benefit from BLAS, you should then use GFqExt instead, which does convert field elements (polynomials) to double by leaving enough room in the evaluation to allow for delayed modular computations.
  • The use of fgemm with a field having ModeTraits::GenericTag is currently broken as you have experienced: there is an asumption in the dynamicPeeling routines that the Helper has the field of a Delayed field helper, which is not the case with generic helpers. This is #162
template <typename Element> 
struct ModeTraits<Givaro::GFqDom<Element> >{typedef typename ModeCategories::ConvertTo<ElementCategories::MachineFloatTag> value;};

To summarize:

  1. using GFqDom over a prime field: you can safely use the above ModeTrait partial specialization. We still need to add a runtime switch to catch the case for e>1
  2. using GFqDom with e>1 should swich to a GenericTag but then requires to fix #162
  3. using GFqExt (assumes e>1): should use a new ConvertTo tag to specify that the ring to be used after conversion is ZRing<double> and not ModularBalanced<double>. This is #163

ClementPernet avatar Feb 27 '18 10:02 ClementPernet

OK, it looks like GFqExt is probably the way to go for now. To give some context, I'm trying to use LinBox's block methods with the matrix embedded in an extension field, but as discussed the fflas::gemm wasn't happy with the matrix embedded in GFqDom. Would GFqExt be the current preferred extension field to use for a small field embedded in a rather large extension field (e.g. GF(3) to GF(3^e) where 10 <= e), or would some other field extension class be better?

Thank you for your help :)

gmh33 avatar Feb 28 '18 01:02 gmh33