Opened 12 years ago

Closed 9 years ago

# memory leak in scalar*vector multiplication

Reported by: Owned by: Dima Pasechnik jason, was major sage-duplicate/invalid/wontfix linear algebra linear algebra, memory leak Maarten Derickx N/A #13304

### Description

Here is an example

```sage: for i in range(1,8):
A=(1/2)*vector([x/2 for x in range(i*1000)])
get_memory_usage()
....:
921.53125
1287.4765625
2111.984375
3577.546875
5867.19140625
9164.109375
... (killed, due to running out of memory)
```

The printed numbers in Mb. Needless to say:

```sage: for i in range(1,8):
....:     A=vector([x/2 for x in range(i*1000)])
....:     get_memory_usage()
....:
828.91015625
829.4453125
829.73046875
830.0
830.55859375
830.75
831.0078125
```

works as expected. (This is with Sage 4.6 on x64, but is not limited to this particular platform: see https://groups.google.com/group/sage-devel/browse_thread/thread/e86f13c78b92a8bb?hl=en. Sage 4.5.3 shows the same behaviour.)

### comment:1 Changed 12 years ago by Dima Pasechnik

Summary: memory leak in scalar*vector mutiplication → memory leak in scalar*vector multiplication

### comment:2 Changed 12 years ago by David Kirkby

FWIW, I've found when building on Solaris with a special library for memory allocation, which allows leaks to be detected, before I got to the

```sage:
```

there was already memory leaked. I think it was only 14 bytes, but once I did a few calculations, more showed up. I think there are quite a few in Sage. Of course, some are more serious than others, but whatever the amount of memory leaked, it shows there's a coding error.

Dave

### comment:3 follow-up:  4 Changed 12 years ago by Jason Grout

As I mentioned on the thread, I tracked this down to a call from the coercion system to create an element of the parent. The coercion system did this when it was trying to figure out the action of the number on the vector:

The problem seems to stem from the lines

```     cdef Element x = X.an_element()
cdef Element y = Y.an_element()
```

inside of the `detect_element_action` function in `coerce_actions.pyx`. Notice:

```sage: v=vector(range(10000))
sage: get_memory_usage()
206.84765625
sage: w=v.parent().an_element()
sage: get_memory_usage()
3321.14453125
```

### comment:4 in reply to:  3 ; follow-up:  12 Changed 12 years ago by Dima Pasechnik

As I mentioned on the thread, I tracked this down to a call from the coercion system to create an element of the parent.

So `w` is a 10000 long vector over "ambient_pid_with_category". I'd call this alone a bug, for this is horribly inefficient. Coercion for module operation could be much better...

My guess is that "an_element()" gets memoised, and retained instead of being destroyed at each for-loop. Indeed:

```sage: for i in [1,2,3,4,1,2,3,4]:
....:
....:     A=(1/2)*vector([x/2 for x in range(i*1000)])
....:     get_memory_usage()
....:
261.58984375
513.59765625
1073.109375
2057.37890625
2057.37890625
2057.37890625
2057.37890625
2057.62890625
sage: for i in [1,3,5,1,3,5]:
A=(1/2)*vector([x/2 for x in range(i*1000)])
get_memory_usage()
....:
2057.62890625
2057.62890625
3614.55078125
3614.55078125
3614.80078125
3615.05078125
```

So we get these huge vectors clogging up the memory, in hope that someone might want to compute in the free modules (over ambient_pid_with_category) of these dimensions again...

Should one just turn the memoisation for modules off completely? This would not cure the coercion inefficiency completely, but at least would prevent this leak...

### comment:5 follow-up:  6 Changed 12 years ago by Jeroen Demeyer

Priority: blocker → major

Why is this a blocker?

### comment:6 in reply to:  5 Changed 12 years ago by Dima Pasechnik

Type: defect → enhancement

Why is this a blocker?

it is not, indeed. After investigating what happens, I forgot to change it to major, sorry.

### comment:7 Changed 12 years ago by Maarten Derickx

This might also be related to #10570 since that ticket shows that there are call stack frames in the coerce_actions framework which stay alive for some reason.

### comment:9 Changed 12 years ago by Maarten Derickx

sorry uploaded a patch to the wrong ticket

### comment:10 Changed 9 years ago by Jeroen Demeyer

Milestone: sage-5.11 → sage-5.12

### comment:11 Changed 9 years ago by For batch modifications

Milestone: sage-6.1 → sage-6.2

### comment:12 in reply to:  4 Changed 9 years ago by Marc Mezzarobba

My guess is that "an_element()" gets memoised, and retained instead of being destroyed at each for-loop.

At least with #14711, the parent and its cached elements appear to be correctly destroyed after each loop turn. However, calling `an_element()` triggers the computation of a basis, and the whole basis is cached!

```sage: for i in [4, 3, 2, 1, 4, 3, 2, 1]:
del A; gc.collect(); A=(1/2)*vector([x/2 for x in range(i*1000)]); get_memory_usage()
....:
4029
2483.984375
4030
1842.5390625
3030
1831.33203125
2030
1831.33203125
1030
2483.984375
4030
1842.54296875
3030
1831.33203125
2030
1831.33203125
```

Possible quick fix, with some code duplication:

• ## src/sage/modules/free_module.py

```diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py
index a61b433..81a626c 100644```
 a class FreeModule_ambient(FreeModule_generic): """ return self def gen(self, i): if i < 0 or i >= self.rank(): raise ValueError, "Generator %s not defined."%i v = self.zero().__copy__() v[i] = self.base_ring()(1) v.set_immutable() return v def basis(self): """ Return a basis for this ambient free module.

But I am not convinced it is such a good idea in general to cache the basis of a `FreeModule_ambient`...

Last edited 9 years ago by Marc Mezzarobba (previous) (diff)

### comment:13 Changed 9 years ago by Marc Mezzarobba

Turns out there is already a more polished version of the fix I was suggesting at #13304.

### comment:14 Changed 9 years ago by Marc Mezzarobba

Milestone: sage-6.2 → sage-duplicate/invalid/wontfix new → needs_review

### comment:15 follow-up:  17 Changed 9 years ago by Dima Pasechnik

Dependencies: → 13304 needs_review → needs_info

perhaps this ticket should at least provide a doctest that this issue is fixed by #13304?

Last edited 9 years ago by Dima Pasechnik (previous) (diff)

### comment:16 Changed 9 years ago by Dima Pasechnik

Dependencies: 13304 → #13304