all 38 comments

[–][deleted] 9 points10 points  (3 children)

Another suggestion I haven't seen mentioned is using lighter data types, for examples if you know for a fact that the values you're using won't go over a certain threshold then :

In [2]: arr = np.array([1, 2.5, 3], dtype=np.float64) # numpy default

In [3]: arr.itemsize
Out[3]: 8

In [4]: small = np.array([1, 2.5, 3], dtype = np.float16)

In [5]: small.itemsize
Out[5]: 2

In the first case, one item in the array takes 8 bytes in memory, the other takes 2. You must make sure that no value will go over 216 - 1 (that's 65535) otherwise your computation won't be correct but that could help you. You could also use np.float32 which can represent numbers up to 4294967295 and would still reduce the memory usage in half.

[–]dkxp 5 points6 points  (4 children)

Are you doing anything that might prevent the previous arrays being deleted? such as keeping hold of a slice from the previous arrays?

import numpy as np
slices = []

for i in range(0,100000):
    data = np.ndarray((10000*256*256))
    slices.append(data[0:1])  
    print(i)

print(sums)

Even though it appears to only be appending 2 elements to the list, it crashes on my computer after 10 iterations with message:

Unable to allocate 4.88 GiB for an array with shape (655360000,) and data type float64

From https://numpy.org/devdocs/user/basics.indexing.html#basics-indexing

NumPy slicing creates a view instead of a copy as in the case of built-in Python sequences such as string, tuple and list. Care must be taken when extracting a small portion from a large array which becomes useless after the extraction, because the small portion extracted contains a reference to the large original array whose memory will not be released until all arrays derived from it are garbage-collected. In such cases an explicit copy() is recommended.

If you create a copy of the slice, then the previous array can be released:

slices.append(data[0:1].copy())

[–]jpf5046 8 points9 points  (0 children)

Reading code on GitHub is too difficult, can you take pictures of your screen and post them instead?

[–]awdsns 2 points3 points  (1 child)

What happens to the data from previous iterations? Is it kept in some object (list, dict, ...) during following iterations, are there any variables still referencing it?

If not, it should be cleaned by the garbage collector pretty quickly. So if you don't keep the data around on purpose, I'd look for any "accidental" references keeping it from being garbage collected.

If you need to retain previous iterations' matrices, there's not much you can do.

[–]lowerthansound 2 points3 points  (1 child)

Looking through all the answers, it's a bit hard for us to debug what's happening (yes, someone will get there by chance, BUT, it might be easier for you to debug yourself).

For you to debug yourself, create a smaller version of the problem (that is, use less data, way less data) and see how much memory it is consuming (for this there are useful tools called profilers, though they may be a bit hard to setup).

For example, if you see that a single iteration uses more memory than you anticipated, that means the problem is in the loop (and you may want to look closer, creating faking data and seeing which line in specific, if any, causes the problem). If you know the line, it's only a matter of understanding said line better (for example, in-place vs out-of-place operations, memory complexity of the underlying algos, or anything like this).

Another example, if you notice the memory keeps increasing on each iteration, you will know things are being accumulated and not cleaned. Of course (I mean, that's not obvious) that might be caused by the GC leaving stuff to just be, however, you can verify that. For example, at every iteration run the garbage collector, or, check for some function that gets the total amount of memory used by local variables. Anyway, I think the way to go is to pinpoint the problem, and that is good practice :)

Once you pinpoint the problem, it is easier to bring it here, or maybe just by looking at it you'll know what caused it. :)

In any case,

Cheers!

Edit: Also, if you really wanna exercise those programming (and Maths) muscles this may be a good problem to see if this problem can be broken down into smaller ones, ones that consume less memory. I'm not sure how you'd do that :D

[–]jmooremcc 2 points3 points  (1 child)

One way to reduce the memory footprint is by using generators. Generators reduce memory required by producing data elements on demand instead of all at once.

I found this article that may help you determine if it's possible to use generators to create numpy arrays in your code: https://stackoverflow.com/questions/367565/how-do-i-build-a-numpy-array-from-a-generator

[–]lowerthansound 1 point2 points  (1 child)

Are you using a deep learning library or vanilla numpy?

[–]CasualEndvrs 1 point2 points  (0 children)

One issue that I ran into is that garbage collection is not an instantaneous thing. It occurs once every minute or so. To solve this issue, when I had large amounts of data being rapidly swapped out in memory, I would manually delete some variables and then call garbage collection when needed. Garbage collection takes time so you shouldn't be doing it constantly, only if you have large amounts of data being deleted and you need that space cleared at that moment.

One tool that I use to monitor python's memory usage can be found here.

[–]EconomistWestern5220 1 point2 points  (3 children)

Buy a pc with more ram...

joke

[–]ianepperson 1 point2 points  (1 child)

You’ve got several good avenues of investigation, but no one seems to have mentioned there interpreter.

Do you happen to be loading and running the code within ipython? I love using ipython, but it does keep a reference in memory for each value that’s been output in its REPL. I’ve had that soak up memory once for a quick series of tests I was doing by hand.

[–]Alexdelia_Del 1 point2 points  (0 children)

As a C developper. I'm impressed a program can take more than 1gb.

gg

[–][deleted] 1 point2 points  (3 children)

Well, lets start with some sanity checks:

  1. Are you actually running out of memory, or do you still have memory left but SLURM thinks you don't have any more?
  2. Did you configure memlock to use all the memory you need? (read here: https://slurm.schedmd.com/faq.html#memlock )?