Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

matrix multiplication over integer mod ring is slow #9888

Open
sagetrac-dmharvey mannequin opened this issue Sep 9, 2010 · 5 comments
Open

matrix multiplication over integer mod ring is slow #9888

sagetrac-dmharvey mannequin opened this issue Sep 9, 2010 · 5 comments

Comments

@sagetrac-dmharvey
Copy link
Mannequin

sagetrac-dmharvey mannequin commented Sep 9, 2010

Sage 4.5.3, 2.6GHz Opteron, Linux

This is ok:

sage: M1 = Matrix([[randrange(3^20) for i in range(100)] for j in range(100)])
sage: M2 = Matrix([[randrange(3^20) for i in range(100)] for j in range(100)])
sage: timeit("M3 = M1 * M2")
5 loops, best of 3: 45.6 ms per loop

(That's about 4 times slower than Magma, but I can put up with that, that's a ticket for another day.)

Here is the problem:

sage: R = Integers(3^20)
sage: M1 = Matrix([[R.random_element() for i in range(100)] for j in range(100)])
sage: M2 = Matrix([[R.random_element() for i in range(100)] for j in range(100)])
sage: timeit("M3 = M1 * M2")
5 loops, best of 3: 877 ms per loop

In other words, I can multiply the matrices over R roughly 20x faster by multiplying over Z and then reducing! That's ridiculous!

Component: performance

Keywords: sd90

Issue created by migration from https://trac.sagemath.org/ticket/9888

@robertwb
Copy link
Contributor

robertwb commented Sep 9, 2010

comment:1

I don't think anything has gone into non-word-sized modulus, so this is probably using totally generic per-element wrapping code :(. Should be an easy fix to get better than this, doing something real would be a bit more work.

@kedlaya
Copy link
Contributor

kedlaya commented Apr 10, 2016

comment:2

I just tried the timings again:

sage: sage: M1 = Matrix([[randrange(3^20) for i in range(100)] for j in range(100)])
sage: sage: M2 = Matrix([[randrange(3^20) for i in range(100)] for j in range(100)])
sage: sage: timeit("M3 = M1 * M2")
125 loops, best of 3: 5.62 ms per loop
sage: sage: R = Integers(3^20)
sage: sage: M1 = Matrix([[R.random_element() for i in range(100)] for j in range(100)])
sage: sage: M2 = Matrix([[R.random_element() for i in range(100)] for j in range(100)])
sage: sage: timeit("M3 = M1 * M2")
5 loops, best of 3: 530 ms per loop

so now the discrepancy is up to a factor of 100!

My recollection is that lifting the multiplication up to Z is in fact the correct algorithmic approach. In practice, this hands the problem off to FLINT, where (in this size range) the multiplication is done multimodular.

@kedlaya
Copy link
Contributor

kedlaya commented Aug 17, 2016

comment:3

See #12177 for a related discussion.

@adeines
Copy link
Mannequin

adeines mannequin commented Oct 22, 2017

Changed keywords from none to sd90

@kedlaya
Copy link
Contributor

kedlaya commented Oct 24, 2017

comment:5

There appears to be special-purpose code using Linbox for modulus up to 223 in sage/matrix/matrix_modn_dense_double.pyx and sage/matrix/matrix_modn_dense_float.pyx. To handle this issue, it would be best to create a file sage/matrix/matrix_modn_dense.pyx in which we create the class Matrix_modn_dense with a special _mul_ method. But we should make sure not to create a regression by disconnecting the existing code for smaller moduli.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants