fflas-ffpack
fflas-ffpack copied to clipboard
FFLAS::fgemm does not compile with Givaro::GFqDom
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
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;};
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 toElement=int64_t
. However, this ModeTraits is determined at compile time where we can not teste==1
and the conversion toModularBalanced<double>
would then be erroneous whenevere>1
. In such a case theModeTrait
should be set toGenericTag
- 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) todouble
by leaving enough room in the evaluation to allow for delayed modular computations. - The use of
fgemm
with a field havingModeTraits::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:
- 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 fore>1
- using GFqDom with
e>1
should swich to a GenericTag but then requires to fix #162 - using GFqExt (assumes
e>1
): should use a new ConvertTo tag to specify that the ring to be used after conversion isZRing<double>
and notModularBalanced<double>
. This is #163
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 :)