ไม่สามารถจัดสรรอาร์เรย์ด้วยรูปร่างและชนิดข้อมูล


116

ฉันประสบปัญหาในการจัดสรรอาร์เรย์ขนาดใหญ่เป็นจำนวนมากบน Ubuntu 18 ในขณะที่ไม่ประสบปัญหาเดียวกันใน MacOS

ฉันพยายามจัดสรรหน่วยความจำสำหรับอาร์เรย์ numpy ที่มีรูปร่าง(156816, 36, 53806) ด้วย

np.zeros((156816, 36, 53806), dtype='uint8')

และในขณะที่ฉันได้รับข้อผิดพลาดบน Ubuntu OS

>>> import numpy as np
>>> np.zeros((156816, 36, 53806), dtype='uint8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
numpy.core._exceptions.MemoryError: Unable to allocate array with shape (156816, 36, 53806) and data type uint8

ฉันไม่ได้รับมันบน MacOS:

>>> import numpy as np 
>>> np.zeros((156816, 36, 53806), dtype='uint8')
array([[[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       ...,

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]]], dtype=uint8)

ฉันเคยอ่านที่ไหนสักแห่งที่np.zerosไม่ควรจัดสรรหน่วยความจำทั้งหมดที่จำเป็นสำหรับอาร์เรย์ แต่สำหรับองค์ประกอบที่ไม่ใช่ศูนย์เท่านั้น แม้ว่าเครื่อง Ubuntu จะมีหน่วยความจำ 64gb ในขณะที่ MacBook Pro ของฉันมีเพียง 16gb

เวอร์ชัน:

Ubuntu
os -> ubuntu mate 18
python -> 3.6.8
numpy -> 1.17.0

mac
os -> 10.14.6
python -> 3.6.4
numpy -> 1.17.0

PS: ล้มเหลวใน Google Colab ด้วย


1
มีกระบวนการอื่น ๆ ที่ทำงานอยู่ในหน่วยความจำหรือไม่?
— BlueRine S

ไม่ฉันลองtopและfree -mคำสั่งเหล่านั้นที่ทำให้เมมฟรี 60GB และอื่น ๆ
— Martin Brisiak

อืม แปลก. นั่นไม่ควรใช้ความจำมากขนาดนั้น Macos ใช้หน่วยความจำเท่าไหร่
— BlueRine S

1
ไม่น่าเป็นไปได้ แต่คุณไม่ได้ใช้งานตัวแปล Python 32 บิตใน Ubuntu ใช่ไหม
— jdehesa

1
np.zerosไม่สร้างsparseเมทริกซ์ อาจมีความล่าช้าในการกรอกเลขศูนย์ แต่ดูstackoverflow.com/q/27464039
— hpaulj

คำตอบ:


116

อาจเกิดจากโหมดการจัดการ overcommitของระบบของคุณ

ในโหมดเริ่มต้น0,

Heuristic overcommit จัดการ ปฏิเสธพื้นที่แอดเดรสที่ชัดเจนมากเกินไป ใช้สำหรับระบบทั่วไป ช่วยให้มั่นใจได้ว่าการจัดสรรไวด์อย่างจริงจังล้มเหลวในขณะที่อนุญาตให้ overcommit เพื่อลดการใช้ swap รูทได้รับอนุญาตให้จัดสรรหน่วยความจำเพิ่มเติมเล็กน้อยในโหมดนี้ นี่คือค่าเริ่มต้น

การฮิวริสติกที่ใช้ไม่ได้รับการอธิบายอย่างชัดเจนที่นี่ แต่จะมีการกล่าวถึงเพิ่มเติมในLinuxเกี่ยวกับ การฮิวริสติกและในหน้านี้

คุณสามารถตรวจสอบโหมด overcommit ปัจจุบันของคุณได้โดยการรัน

$ cat /proc/sys/vm/overcommit_memory
0

ในกรณีนี้คุณกำลังจัดสรร

>>> 156816 * 36 * 53806 / 1024.0**3
282.8939827680588

~ 282 GB และเคอร์เนลก็พูดได้ดีอย่างชัดเจนว่าไม่มีทางที่ฉันจะสามารถยอมรับเพจทางกายภาพจำนวนมากนั้นได้และปฏิเสธการจัดสรร

ถ้า (ในฐานะรูท) คุณเรียกใช้:

$ echo 1 > /proc/sys/vm/overcommit_memory

การดำเนินการนี้จะเปิดใช้งานโหมด "always overcommit" และคุณจะพบว่าระบบจะอนุญาตให้คุณทำการจัดสรรไม่ว่าจะมีขนาดใหญ่เพียงใดก็ตาม

ฉันทดสอบสิ่งนี้ด้วยตัวเองในเครื่องที่มี RAM 32 GB ด้วยโหมด overcommit 0ฉันยังได้รับ a MemoryErrorแต่หลังจากเปลี่ยนกลับเป็น1ใช้งานได้:

>>> import numpy as np
>>> a = np.zeros((156816, 36, 53806), dtype='uint8')
>>> a.nbytes
303755101056

จากนั้นคุณสามารถดำเนินการต่อและเขียนไปยังตำแหน่งใดก็ได้ภายในอาร์เรย์และระบบจะจัดสรรเพจทางกายภาพเฉพาะเมื่อคุณเขียนลงในเพจนั้นอย่างชัดเจน ดังนั้นคุณสามารถใช้สิ่งนี้ด้วยความระมัดระวังสำหรับอาร์เรย์แบบกระจัดกระจาย


2
นี่เป็นคุณสมบัติเฉพาะของเคอร์เนลลินุกซ์ดังนั้นจึงไม่มีสิ่งที่เทียบเท่าโดยตรงบน MacOS แม้ว่าอาจจะคล้ายกันก็ตาม ฉันไม่คิดว่าการตั้งค่าเคอร์เนลสองชั้นบน Mac จะง่ายเหมือนกัน
— Iguananaut

1
@Iguananaut ความหมายที่แท้จริงของคำเตือน "ด้วยความระมัดระวัง" คืออะไร? กล่าวคือ. สถานการณ์ที่เลวร้ายที่สุดของสิ่งที่เกิดขึ้นกับเซิร์ฟเวอร์ Ubuntu 18 ที่มี GTX 1080 GPU คืออะไร?
— mLstudent33

1
@ mLstudent33 สำหรับหนึ่งสิ่งนี้ไม่เกี่ยวข้องกับ GPU ของคุณซึ่งมีหน่วยความจำของตัวเอง ทั้งหมดที่ฉันหมายถึงคือคุณยังสามารถเติมหน่วยความจำของคุณได้ - ทุกครั้งที่คุณเขียนลงในบางเพจในหน่วยความจำหน้านั้น (โดยทั่วไปคือ 4k ไบต์) จะต้องถูกกำหนดให้เป็นหน่วยความจำกายภาพ ดังนั้นสถานการณ์ที่เลวร้ายที่สุดคือคุณมีหน่วยความจำไม่เพียงพอ
— Iguananaut

1
การเปลี่ยนแปลงนี้มีผลทันทีหรือเราต้องรีสตาร์ทเชลล์หรือตัวเครื่องเอง?
— dumbledad

2
จะมีผลทันที แต่จะไม่คงอยู่หลังจากรีบูตโดยไม่มีมาตรการเพิ่มเติม ค้นหาคำถามอื่น ๆ เกี่ยวกับวิธีที่ดีที่สุดใน/proc/sysการตั้งค่าการแจกจ่ายของคุณ
— Iguananaut

53

ฉันมีปัญหาเดียวกันนี้ใน Window และเจอวิธีแก้ปัญหานี้ ดังนั้นหากมีคนพบปัญหานี้ใน Windows วิธีแก้ปัญหาสำหรับฉันคือการเพิ่มขนาดไฟล์เพจเนื่องจากเป็นปัญหาหน่วยความจำ overcommitment สำหรับฉันเช่นกัน

วินโดว์ 8

  1. บนแป้นพิมพ์กด WindowsKey + X จากนั้นคลิกระบบในเมนูป๊อปอัป
  2. แตะหรือคลิกการตั้งค่าระบบขั้นสูง คุณอาจถูกขอรหัสผ่านผู้ดูแลระบบหรือเพื่อยืนยันตัวเลือกของคุณ
  3. บนแท็บขั้นสูงภายใต้ประสิทธิภาพให้แตะหรือคลิกการตั้งค่า
  4. แตะหรือคลิกแท็บขั้นสูงจากนั้นภายใต้หน่วยความจำเสมือนให้แตะหรือคลิกเปลี่ยนแปลง
  5. ล้างกล่องกาเครื่องหมายจัดการขนาดไฟล์เพจสำหรับไดรฟ์ทั้งหมดโดยอัตโนมัติ
  6. ภายใต้ไดรฟ์ [Volume Label] ให้แตะหรือคลิกไดรฟ์ที่มีไฟล์เพจจิ้งที่คุณต้องการเปลี่ยนแปลง
  7. แตะหรือคลิกขนาดที่กำหนดเองป้อนขนาดใหม่เป็นเมกะไบต์ในกล่องขนาดเริ่มต้น (MB) หรือขนาดสูงสุด (MB) แตะหรือคลิกตั้งค่าจากนั้นแตะหรือคลิกตกลง
  8. รีบูตระบบของคุณ

Windows 10

  1. กดปุ่ม Windows
  2. พิมพ์ SystemPropertiesAdvanced
  3. คลิก Run as administrator
  4. ภายใต้ประสิทธิภาพคลิกการตั้งค่า
  5. เลือกแท็บขั้นสูง
  6. เลือกเปลี่ยน ...
  7. ยกเลิกการเลือกจัดการขนาดไฟล์เพจโดยอัตโนมัติสำหรับไดรฟ์ทั้งหมด
  8. จากนั้นเลือกขนาดที่กำหนดเองและกรอกขนาดที่เหมาะสม
  9. กด Set จากนั้นกด OK จากนั้นออกจากกล่องโต้ตอบ Virtual Memory, Performance Options และ System Properties
  10. รีบูตระบบของคุณ

หมายเหตุ: ฉันมีหน่วยความจำไม่เพียงพอในระบบของฉันสำหรับ ~ 282GB ในตัวอย่างนี้ แต่สำหรับกรณีเฉพาะของฉันสิ่งนี้ใช้งานได้

แก้ไข

จากที่นี่คำแนะนำที่แนะนำสำหรับขนาดไฟล์เพจ:

มีสูตรคำนวณขนาดไฟล์เพจที่ถูกต้อง ขนาดเริ่มต้นคือครึ่งหนึ่ง (1.5) x จำนวนหน่วยความจำระบบทั้งหมด ขนาดสูงสุดคือสาม (3) x ขนาดเริ่มต้น สมมติว่าคุณมีหน่วยความจำ 4 GB (1 GB = 1,024 MB x 4 = 4,096 MB) ขนาดเริ่มต้นจะเป็น 1.5 x 4,096 = 6,144 MB และขนาดสูงสุดคือ 3 x 6,144 = 18,432 MB

บางสิ่งที่ควรทราบจากที่นี่ :

อย่างไรก็ตามสิ่งนี้ไม่ได้คำนึงถึงปัจจัยสำคัญอื่น ๆ และการตั้งค่าระบบที่อาจเป็นลักษณะเฉพาะสำหรับคอมพิวเตอร์ของคุณ อีกครั้งให้ Windows เลือกสิ่งที่จะใช้แทนการใช้สูตรตามอำเภอใจที่ทำงานบนคอมพิวเตอร์เครื่องอื่น

นอกจากนี้:

การเพิ่มขนาดไฟล์เพจอาจช่วยป้องกันความไม่เสถียรและการหยุดทำงานใน Windows อย่างไรก็ตามเวลาในการอ่าน / เขียนของฮาร์ดไดรฟ์จะช้ากว่าที่ควรจะเป็นหากข้อมูลอยู่ในหน่วยความจำคอมพิวเตอร์ของคุณ การมีไฟล์หน้าที่ใหญ่ขึ้นจะเพิ่มงานพิเศษให้กับฮาร์ดไดรฟ์ของคุณทำให้ทุกอย่างทำงานช้าลง ขนาดไฟล์เพจควรเพิ่มขึ้นเมื่อพบข้อผิดพลาดหน่วยความจำไม่เพียงพอและเป็นการแก้ไขชั่วคราวเท่านั้น ทางออกที่ดีกว่าคือการเพิ่มหน่วยความจำให้กับคอมพิวเตอร์มากขึ้น


ตอนนี้คุณมีการตั้งค่าขนาดที่กำหนดเอง (ขนาดเริ่มต้น + ขนาดสูงสุด) แบบใด ไม่แน่ใจว่าจะจัดสรรให้ตัวเองได้
— เท่าไร

1
@Azizbro ฉันกลับไปใช้ค่าเริ่มต้นแล้ว แต่เพิ่งปรับค่าจนกระทั่งข้อผิดพลาดหน่วยความจำไม่เพียงพอหายไป
— พักฟื้นของ

ฉันทำสิ่งนี้แล้วก็ยังได้รับMemoryError: Unable to allocate 10.3 PiB for an array with shape (38137754, 38137754) and data type float64
— george.adams1

24

ฉันเจอปัญหานี้ใน Windows ด้วย วิธีการแก้ปัญหาสำหรับผมคือการเปลี่ยนจาก 32 บิตเป็นรุ่น 64 บิตของงูหลาม อันที่จริงซอฟต์แวร์ 32 บิตเช่น CPU 32 บิตสามารถรองรับ RAM ได้สูงสุด 4 GB (2 ^ 32) ดังนั้นหากคุณมี RAM มากกว่า 4 GB เวอร์ชัน 32 บิตจะไม่สามารถใช้ประโยชน์จากมันได้

ด้วย Python เวอร์ชัน 64 บิต (อันที่ชื่อx86-64ในหน้าดาวน์โหลด) ปัญหาก็หายไป

คุณสามารถตรวจสอบเวอร์ชันที่คุณมีได้โดยป้อนล่าม ตอนนี้ที่เป็นเวอร์ชัน 64 บิตมี: Python 3.7.5rc1 (tags/v3.7.5rc1:4082f600a5, Oct 1 2019, 20:28:14) [MSC v.1916 64 bit (AMD64)]โดยที่ [MSC v.1916 64 บิต (AMD64)] หมายถึง "Python 64 บิต"

หมายเหตุ : ณ เวลาที่เขียนนี้ (พฤษภาคม 2020) matplotlibไม่สามารถใช้ได้บน python39 ดังนั้นฉันแนะนำให้ติดตั้ง python37, 64 บิต

แหล่งที่มา:


2
ฉันจะป้อนล่ามได้อย่างไร?
— Shayan

แก้ไขปัญหาของฉันด้วย ใช้ Pycharm ถอนการติดตั้งเวอร์ชัน 32 บิตติดตั้ง 64 บิตหนึ่งใหม่เปลี่ยนตัวแปลโครงการเป็น python 64 บิตใหม่
— Jason Goal

3

ในกรณีของฉันการเพิ่มแอตทริบิวต์ dtype เปลี่ยน dtype ของอาร์เรย์เป็นประเภทที่เล็กลง (จาก float64 เป็น uint8) ลดขนาดอาร์เรย์เพียงพอที่จะไม่โยน MemoryError ใน Windows (64 บิต)

จาก

mask = np.zeros(edges.shape)

ถึง

mask = np.zeros(edges.shape,dtype='uint8')

1

บางครั้งข้อผิดพลาดนี้จะปรากฏขึ้นเนื่องจากเคอร์เนลถึงขีด จำกัด แล้ว ลองรีสตาร์ทเคอร์เนลทำซ้ำตามขั้นตอนที่จำเป็น


4
โปรดอ้างอิง: stackoverflow.com/help/how-to-answer Good พยายาม
— Kishan Mehta

1

เปลี่ยนประเภทข้อมูลเป็นประเภทอื่นที่ใช้หน่วยความจำน้อยลง สำหรับฉันฉันเปลี่ยนประเภทข้อมูลเป็น numpy.uint8:

data['label'] = data['label'].astype(np.uint8)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.