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

Very inefficient scalar multiplication on FreeModule_ambient with somewhat large rank #13304

Closed
dansme opened this issue Jul 27, 2012 · 29 comments

Comments

@dansme
Copy link

dansme commented Jul 27, 2012

As reported in a thread in sage-support trivial scalar multiplication in FreeModule_ambient can be extremely slow or lead to out of memory errors:

n = 10000
v = vector([0]*n)   # ok so far
v2 = v/1            # kaboom

The problem is that, during coercion, _an_element_impl() and in turn gen(0) of FreeModule_ambient gets called. The default implementation of gen calls basis(), computing the entire standard basis, and then returns the first basis vector.

CC: @jdemeyer

Component: linear algebra

Author: Daniel Smertnig, Marc Mezzarobba

Branch/Commit: 8f09d51

Reviewer: Vincent Delecroix

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

@dansme dansme added this to the sage-5.11 milestone Jul 27, 2012
@dansme dansme self-assigned this Jul 27, 2012
@dansme
Copy link
Author

dansme commented Jul 27, 2012

comment:1

Attachment: trac_13304_gen_speedup.patch.gz

The patch overrides gen in FreeModule_ambient to avoid generating the entire standard basis.

@sagetrac-tfeulner
Copy link
Mannequin

sagetrac-tfeulner mannequin commented Aug 30, 2012

comment:3

The change looks fine to me and passes all tests. Maybe you should

  • fill in your real name as Author of this ticket
  • add your name to the author section of the file
  • mark the doctest with the ticket number as an in-line comment
  • explain the speed efficiency gained after applying the patch.

@nbruin
Copy link
Contributor

nbruin commented Aug 30, 2012

comment:4

It's possible that calling base_ring().one_element() is a bit faster than converting the integer 1 into the ring every time. The method one_elementnormally gets cached.

What's more, previously, asking for one basis element triggered basis computation and caching. After that, getting basis elements should be fast. With your patch this caching doesn't get triggered by asking for one basis vector any more. Code that previously benefited m might see a decrease in speed (which can be solved by first explicitly asking for the whole basis to trigger caching).

It might still be a good idea to not cache, but you might document the possible pitfall.

@sagetrac-tfeulner
Copy link
Mannequin

sagetrac-tfeulner mannequin commented Aug 31, 2012

comment:5

The question is, in which situations do we actually ask for the basis of the ambient space? I found out that there is a similar problem when constructing subspaces, see
sage-devel. Unfortunately, this is not solved with this patch.

Surprisingly, there is a difference between the fields GF(4, 'a') and QQ.

@jdemeyer jdemeyer modified the milestones: sage-5.11, sage-5.12 Aug 13, 2013
@nathanncohen
Copy link
Mannequin

nathanncohen mannequin commented Dec 2, 2013

comment:7

(from the previous comments, it looks like the patch in its current state is not waiting for a review)

@sagetrac-vbraun-spam sagetrac-vbraun-spam mannequin modified the milestones: sage-6.1, sage-6.2 Jan 30, 2014
@mezzarobba
Copy link
Member

comment:9

See also #10262.

Replying to @nbruin:

What's more, previously, asking for one basis element triggered basis computation and caching. After that, getting basis elements should be fast.

If I understand correctly, the basis we are talking about is essentially the identity matrix. In fact, I am not convinced caching it (strongly at least) is such a good idea even in general—either recomputing it or computing whatever information one really needs instead sounds better in all cases I can think of. But in any case I think it is insane to call a function that may keep in cache a basis of, say, ℤ10000, unless one absolutely needs the whole basis!

@mezzarobba
Copy link
Member

Author: Daniel Smertnig, Marc Mezzarobba

@mezzarobba
Copy link
Member

@mezzarobba
Copy link
Member

New commits:

3c87ef3Trac 13304: FreeModule_Ambient.gen speedup
8fd7f88Implement reviewer suggestions, + cosmetic changes

@mezzarobba
Copy link
Member

Commit: 8fd7f88

@mezzarobba
Copy link
Member

comment:11

I opened a separate ticket (#15953) for the more general issue of whether and when to cache the basis.

@sagetrac-vbraun-spam sagetrac-vbraun-spam mannequin modified the milestones: sage-6.2, sage-6.3 May 6, 2014
@sagetrac-vbraun-spam sagetrac-vbraun-spam mannequin removed this from the sage-6.3 milestone Aug 10, 2014
@fchapoton
Copy link
Contributor

@fchapoton
Copy link
Contributor

comment:15

I just made a small clean-up and checked that doc builds and look nice.


New commits:

8fba50fMerge with 6.4.beta4
8f09d51trac #13304 put raise statement into py3 shape, plus minor cleanup

@fchapoton
Copy link
Contributor

Changed commit from 8fd7f88 to 8f09d51

@mezzarobba
Copy link
Member

comment:16

Frédéric, did you review the commits prior to yours?

@videlec
Copy link
Contributor

videlec commented Feb 8, 2015

Reviewer: Vincent Delecroix

@videlec
Copy link
Contributor

videlec commented Feb 8, 2015

comment:17

Hello,

You got it right for integer vectors but the generic constructor of FreeModuleElement_generic_dense does call the basis in a very stupid way

    coefficient_ring = parent.basis()[0][0].parent()

In particular the following also takes life time for the very same reason

sage: V = ZZ['x']^50000
sage: V([0]*50000)

@mezzarobba
Copy link
Member

comment:18

Replying to @videlec:

You got it right for integer vectors but the generic constructor of FreeModuleElement_generic_dense does call the basis in a very stupid way

    coefficient_ring = parent.basis()[0][0].parent()

In particular the following also takes life time for the very same reason

sage: V = ZZ['x']^50000
sage: V([0]*50000)

Does it make the solution in this ticket inadequate? Or is it just a similar problem that can be handled separately?

@videlec
Copy link
Contributor

videlec commented Feb 8, 2015

comment:19

Replying to @mezzarobba:

Replying to @videlec:

You got it right for integer vectors but the generic constructor of FreeModuleElement_generic_dense does call the basis in a very stupid way

    coefficient_ring = parent.basis()[0][0].parent()

In particular the following also takes life time for the very same reason

sage: V = ZZ['x']^50000
sage: V([0]*50000)

Does it make the solution in this ticket inadequate? Or is it just a similar problem that can be handled separately?

Second option. It is just a one line change (that I can even do myself). Do you prefer this one line change to be on another ticket?

@mezzarobba
Copy link
Member

comment:20

Replying to @videlec:

Second option. It is just a one line change (that I can even do myself). Do you prefer this one line change to be on another ticket?

No, please feel free to do it here if you like. (I can't do it myself at the moment.)

@videlec
Copy link
Contributor

videlec commented Feb 8, 2015

comment:21

Wow! Because of #11751 that introduces a very weird behavior the call to .basis() is somewhat unavoidable. Jeroen already pointed that out in #11751 and proposed to revert the changes. I am in favor of also reverting the changes. Might be better within another ticket?

@videlec
Copy link
Contributor

videlec commented Feb 20, 2015

comment:22

Replying to @videlec:

Wow! Because of #11751 that introduces a very weird behavior the call to .basis() is somewhat unavoidable. Jeroen already pointed that out in #11751 and proposed to revert the changes. I am in favor of also reverting the changes. Might be better within another ticket?

The problem mentioned in comment:17 and the follow-ups needs #17585. In the meantime I am running the test for this branch on sage-6.6.beta0 and will set a positive review accordinlgy.

Vincent

@jdemeyer
Copy link

comment:24

I think that #17585 provides a better and more fundamental fix to the problem: the line

coefficient_ring = parent.basis()[0][0].parent()

is just removed completely.

@jdemeyer
Copy link

comment:25

Actually, #17585 fixes

sage: V = ZZ['x']^50000
sage: V([0]*50000)

but not

sage: vector([0]*50000)/1

Since this ticket looks quite independent of #17585, it makes sense to have both.

I do suggest to add the two doctests above, since they clearly test different issues.

@jdemeyer
Copy link

Work Issues: add doctest

@videlec
Copy link
Contributor

videlec commented Feb 20, 2015

comment:26

Replying to @jdemeyer:

Actually, #17585 fixes

sage: V = ZZ['x']^50000
sage: V([0]*50000)

but not

sage: vector([0]*50000)/1

Since this ticket looks quite independent of #17585, it makes sense to have both.

I do suggest to add the two doctests above, since they clearly test different issues.

The first one should go in #17585, no?

@jdemeyer
Copy link

Changed work issues from add doctest to none

@jdemeyer
Copy link

comment:27

Sorry, there was a misunderstanding. I thought that this ticket fixed both issues.

@vbraun
Copy link
Member

vbraun commented Feb 21, 2015

Changed branch from public/ticket/13304 to 8f09d51

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

7 participants