形状とデータ型で配列を割り当てることができません


114

MacOSでは同じ問題に直面していないのに、Ubuntu18でnumpyに巨大な配列を割り当てるという問題に直面しています。

形状のあるnumpy配列にメモリを割り当てようとし(156816, 36, 53806) ています

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

UbuntuOSでエラーが発生している間

>>> 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のメモリがありますが、私のMacBookProには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:GoogleColabでも失敗しました


1
メモリ内で実行されている他のプロセスはありますか?
BlueRineS19年

いいえ、私は試しましたがtopfree -m60GBのmemを無料で押し込むコマンド
MartinBrisiak19年

うーん。変だ。それはそれほど多くのメモリを消費するべきではありません。Macosでどのくらいのメモリを占有しましたか?
BlueRineS19年

1
可能性は低いですが、Ubuntuで32ビットのPythonインタープリターを実行していることはありませんか?
jdehesa

1
np.zerossparseマトリックスを作成しません。ゼロを埋めるのに遅れがあるかもしれません。ただし、stackoverflow.com
q / 27464039 –hpaulj19年

回答:


113

これは、システムのオーバーコミット処理モードが原因である可能性があります。

デフォルトモードでは、0

ヒューリスティックなオーバーコミット処理。アドレス空間の明らかなオーバーコミットは拒否されます。一般的なシステムに使用されます。オーバーコミットを許可してスワップの使用量を削減しながら、深刻なワイルド割り当てが失敗することを保証します。このモードでは、rootはわずかに多くのメモリを割り当てることができます。これがデフォルトです。

使用される正確なヒューリスティックはここでは十分に説明されていませんが、これについてはLinuxのコミットヒューリスティックこのページで詳しく説明 しています

を実行すると、現在のオーバーコミットモードを確認できます。

$ cat /proc/sys/vm/overcommit_memory
0

この場合、あなたは割り当てています

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

〜282 GBであり、カーネルは明らかに、これほど多くの物理ページをこれにコミットする方法はないと言っており、割り当てを拒否します。

(ルートとして)実行する場合:

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

これにより、「常にオーバーコミット」モードが有効になり、実際にシステムでは、割り当ての大きさに関係なく(少なくとも64ビットメモリアドレス指定内で)割り当てを行うことができます。

私はこれを32GBのRAMを搭載したマシンで自分でテストしました。オーバーコミットモードで0は、も取得しましたがMemoryError、元に戻す1と機能します。

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

その後、先に進んで配列内の任意の場所に書き込むことができ、システムは、そのページに明示的に書き込む場合にのみ物理ページを割り当てます。したがって、これをスパース配列に注意して使用できます。


2
これは特にLinuxカーネルの機能であるため、MacOSに直接同等のものは必ずしもありませんが、似たようなものである可能性があります。Macではカーネル設定をいじるのは簡単ではないと思います。
イグアナナウト

1
@Iguananaut「注意して」警告の正確な意味は何ですか?すなわち。GTX 1080GPUを搭載したUbuntu18サーバーでこれに問題が発生する最悪のシナリオは何ですか?
mLstudent 3319

1
@ mLstudent33 1つは、これは独自のメモリを備えたGPUとは何の関係もありません。つまり、メモリをいっぱいにすることができます。メモリ内のあるページに書き込むたびに、そのページ(通常は4kバイト)を物理メモリにコミットする必要があります。したがって、最悪のシナリオは、メモリが不足することです。
イグアナナウト

1
この変更はすぐに有効になりますか、それともシェルまたはマシン自体を再起動する必要がありますか?
ダンブルダッド

2
すぐに有効になりますが、追加の対策がなければ再起動後も持続しません。/proc/sysディストリビューションの設定を保持する最善の方法に関する他の質問を検索してください。
Iguananaut

53

私はウィンドウズでこれと同じ問題を抱えていて、この解決策に出くわしました。したがって、誰かがWindowsでこの問題に遭遇した場合、それは私にとってもメモリのオーバーコミットメントの問題であったため、私にとっての解決策はページファイルのサイズを増やすことでした。

ウィンドウズ8

  1. キーボードでWindowsKey + Xを押してから、ポップアップメニューの[システム]をクリックします
  2. [システムの詳細設定]をタップまたはクリックします。管理者パスワードの入力または選択の確認を求められる場合があります
  3. [詳細設定]タブの[パフォーマンス]で、[設定]をタップまたはクリックします。
  4. [詳細設定]タブをタップまたはクリックし、[仮想メモリ]で[変更]をタップまたはクリックします
  5. [すべてのドライブのページングファイルサイズを自動的に管理する]チェックボックスをオフにします。
  6. [ドライブ] [ボリュームラベル]で、変更するページングファイルが含まれているドライブをタップまたはクリックします
  7. [カスタムサイズ]をタップまたはクリックし、[初期サイズ(MB)]または[最大サイズ(MB)]ボックスに新しいサイズをメガバイト単位で入力し、[設定]をタップまたはクリックしてから、[OK]をタップまたはクリックします。
  8. システムを再起動します

ウィンドウズ10

  1. Windowsキーを押します
  2. SystemPropertiesAdvancedと入力します
  3. [管理者として実行]をクリックします
  4. [パフォーマンス]で、[設定]をクリックします
  5. [詳細設定]タブを選択します
  6. [変更...]を選択します
  7. [すべてのドライブのページングファイルサイズを自動的に管理する]チェックボックスをオフにします
  8. 次に、カスタムサイズを選択し、適切なサイズを入力します
  9. [設定]を押してから[OK]を押して、[仮想メモリ、パフォーマンスオプション、およびシステムプロパティ]ダイアログを終了します
  10. システムを再起動します

注:この例では、システムに約282GBの十分なメモリがありませんでしたが、特定のケースではこれで機能しました。

編集

ここから、ページファイルサイズの推奨推奨事項:

正しいページファイルサイズを計算するための式があります。初期サイズは、1.5(1.5)xシステムメモリの合計量です。最大サイズは3x初期サイズです。したがって、4 GB(1 GB = 1,024 MB x 4 = 4,096 MB)のメモリがあるとします。初期サイズは1.5x 4,096 = 6,144 MBで、最大サイズは3 x 6,144 = 18,432MBです。

ここから覚えておくべきいくつかの事柄:

ただし、これには、コンピューターに固有のその他の重要な要素やシステム設定は考慮されていません。繰り返しになりますが、別のコンピューターで機能する任意の数式に依存するのではなく、Windowsに使用するものを選択させます。

また:

ページファイルのサイズを大きくすると、Windowsの不安定性やクラッシュを防ぐのに役立つ場合があります。ただし、ハードドライブの読み取り/書き込み時間は、データがコンピュータのメモリにある場合よりもはるかに遅くなります。ページファイルが大きくなると、ハードドライブに余分な作業が追加され、他のすべての実行速度が低下します。ページファイルサイズは、メモリ不足エラーが発生した場合にのみ、一時的な修正としてのみ増やす必要があります。より良い解決策は、コンピュータにメモリを追加することです。


現在、どのようなカスタムサイズ(初期サイズ+最大サイズ)の設定がありますか?わからないどのくらい自分のために割り当てるために
Azizbro

1
@Azizbroデフォルトに戻りましたが、メモリ不足エラーが消えるまで値を調整しました。
繰り返し

私はこれを実行しましたが、まだ取得していますMemoryError: Unable to allocate 10.3 PiB for an array with shape (38137754, 38137754) and data type float64
george.adams1 2020

24

私はWindowsでもこの問題に遭遇しました。私にとっての解決策は、Pythonの32ビットバージョンから64ビットバージョン切り替えることでした。実際、32ビットCPUのような32ビットソフトウェアは、最大4 GBのRAM(2 ^ 32)に対応できます。したがって、4 GBを超えるRAMがある場合、32ビットバージョンではそれを利用できません。

64ビットバージョンのPython(ダウンロードページで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)]は「64ビットPython」を意味します。

:この記事の執筆時点(2020年5月)では、matplotlibはpython39で使用できないため、python37、64ビットをインストールすることをお勧めします。

出典:


1
通訳を入力するにはどうすればよいですか?
Shayan

私の問題も解決しました。Pycharmを使用します。32ビットバージョンをアンインストールし、64ビットバージョンを再インストールし、プロジェクトインタープリターを新しい64ビットPythonに変更しました。
ジェイソンゴール

3

私の場合、dtype属性を追加すると、配列のdtypeがより小さな型(float64からuint8)に変更され、Windows(64ビット)でMemoryErrorがスローされないように配列サイズが十分に小さくなりました。

から

mask = np.zeros(edges.shape)

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


1

データ型を、メモリの使用量が少ない別のデータ型に変更します。私の場合、データ型をnumpy.uint8に変更します。

data['label'] = data['label'].astype(np.uint8)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.