Frage Warum stürzt Python ab, wenn ich dieses numpige Array summiere?


Ich arbeite an Ubuntu 14.04 mit Python 3.4 (Numpy 1.9.2 und PIL.Image 1.1.7). Folgendes mache ich:

>>> from PIL import Image
>>> import numpy as np

>>> img = Image.open("./tifs/18015.pdf_001.tif")
>>> arr = np.asarray(img)
>>> np.shape(arr)
(5847, 4133)

>>> arr.dtype
dtype('bool')

# all of the following four cases where I incrementally increase
# the number of rows to 700 are done instantly
>>> v = arr[1:100,1:100].sum(axis=0)
>>> v = arr[1:500,1:100].sum(axis=0)
>>> v = arr[1:600,1:100].sum(axis=0)
>>> v = arr[1:700,1:100].sum(axis=0)

# but suddenly this line makes Python crash
>>> v = arr[1:800,1:100].sum(axis=0)

fish: Job 1, “python3” terminated by signal SIGSEGV (Address boundary error)

Es scheint mir, als hätte Python plötzlich keine Speicher mehr. Wenn das der Fall ist - wie kann ich Python mehr Speicher zuweisen? Wie ich von htop sehen kann, ist meine 32GB Speicherkapazität nicht einmal ausgelaugt.

Sie können das TIFF-Bild herunterladen Hier.


Wenn ich ein leeres boolesches Array erstelle, setze die Pixel explizit und wende dann die Summierung an - dann funktioniert es:

>>> arr = np.empty((h,w), dtype=bool)
>>> arr.setflags(write=True)

>>> for r in range(h):
>>>     for c in range(w):
>>>         arr.itemset((r,c), img.getpixel((c,r)))

>>> v=arr.sum(axis=0)

>>> v.mean()
5726.8618436970719

>>> arr.shape
(5847, 4133)

Aber dieser "Workaround" ist nicht sehr zufriedenstellend, da das Kopieren jedes Pixels viel zu lange dauert - vielleicht gibt es eine schnellere Methode?


6
2018-03-17 17:54


Ursprung


Antworten:


Ich kann Ihren segfault mit numpy v1.8.2 / PIL v1.1.7 reproduzieren, das von den Ubuntu-Repositories installiert wurde.

  • Wenn ich numpy 1.8.2 in einem virtualenv mit pip installiere (immer noch mit PIL v1.7.1 von den Ubuntu Repos), dann sehe ich den segfault nicht mehr.

  • Wenn ich das Gegenteil tue (PIL v1.1.7 mit pip installieren und numpy v1.8.2 von den Ubuntu-Repos verwenden), bekomme ich immer noch den segfault.

Dies führt mich zu der Annahme, dass es durch einen alten Fehler in der Anzahl verursacht wurde. Ich war nicht in der Lage, einen guten Kandidaten in numpy's issue tracker zu finden, aber ich vermute, dass die Aktualisierung von numpy (z.B. von der aktuellen Quelle oder über pip) das Problem wahrscheinlich lösen würde.

Eine Problemumgehung besteht darin, den Bildmodus zu konvertieren "P" (vorzeichenlose 8-Bit-Ints), bevor Sie das Array erstellen und es dann wieder in Boolean konvertieren:

arr2 = np.asarray(img.convert("P")).astype(np.bool)
v = arr2[1:800,1:100].sum(axis=0)

3
2018-03-17 20:20