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


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.