web-dev-qa-db-ja.com

Python 64ビットウィンドウでの32ビットメモリ制限

理解できないようなメモリの問題が発生しています。

私は8 GBのメモリを搭載したWindows 7 64ビットマシンで32ビットpythonプログラムを実行しています。

プログラムは、5,118個の圧縮されたnumpyファイル(npz)を読み取ります。 Windowsは、ファイルがディスク上で1.98 GBを占めると報告しています

各npzファイルには2つのデータが含まれています。「arr_0」はタイプnp.float32で、「arr_1」はタイプnp.uint8です。

pythonスクリプトは、各ファイルを読み取り、データを2つのリストに追加して、ファイルを閉じます。

ファイル4284/5118の周りでプログラムがMemoryExceptionをスローします

ただし、タスクマネージャーによると、エラーが発生したときのpython.exe * 32のメモリ使用量は1,854,848K〜= 1.8GBです。私の8 GBの制限、または32ビットプログラムの想定される4 GBの制限よりはるかに少ない。

プログラムでメモリエラーをキャッチし、レポートします。各リストの長さは4285です。最初のリストには、合計1,928,588,480 float32の〜= 229.9 MBのデータが含まれています。 2番目のリストには、12,342,966,272 uint8の〜= 1,471.3MBのデータが含まれています。

だから、すべてがチェックアウトしているようです。メモリエラーが発生する箇所を除きます。私には絶対に多くのメモリがあり、それがクラッシュするファイルは〜800KBなので、巨大なファイルの読み取りに失敗しません。

また、ファイルは破損していません。事前にそのメモリをすべて使用していなければ、問題なく読み取ることができます。

混乱を招くように、これはすべて私のLinuxマシンで正常に動作するようです(ただし、Windowsマシンでは8 GBであるのに対し、16 GBのメモリを搭載しています)が、それでもマシンのRAMこの問題の原因です。

別の2GBのデータを割り当てることができるはずであるのに、Pythonがメモリエラーをスローするのはなぜですか?

20
Erotemic

プロセスが4GBにアクセスできるはずだと思う理由がわかりません。 MSDNの Windowsリリースのメモリ制限 によると、64ビットのWindows 7では、デフォルトの32ビットプロセスは2GBを取得します。

それで、これを回避する方法はありますか?

さて、IMAGE_FILE_LARGE_ADDRESS_AWAREフラグを使用する32ビットPythonのカスタムビルドを作成し、numpyと他のすべての拡張モジュールを再ビルドできます。 large-address-awareフラグを指定して実行すると、関連するすべてのコードが本当に安全であるとは保証できません。十分な可能性はありますが、誰かがすでにそれを実行してテストしていない限り、「良い可能性」は誰もが知っている可能性が最も高いものです。

または、より明確には、代わりに64ビットPythonを使用するだけです。


物理的なRAMの量はまったく関係ありません。 RAMが8GBの場合、「8GBの制限」があると思われるかもしれませんが、それでは動作しません。システムは、すべてのRAMに加えて、必要なスワップ領域をすべて取り、アプリ間で分割します。アプリは、8 GBのマシンでもメモリエラーを発生させることなく、20 GBの仮想メモリを取得できる場合があります。一方、32ビットアプリは4 GBを超えるアクセスができず、OSはそのアドレススペースの一部(デフォルトではWindowsの半分)を使用するため、8 GBのマシンでも2 GBしか取得できませんそれは他に何も実行していません。 (最新のOSで「他に何も実行していない」可能性があるというわけではありませんが、私が何を言っているかはご存じでしょう。)


では、なぜこれがLinuxボックスで機能するのですか?

あなたのLinuxボックスは32ビットプロセスに3.5GBの仮想アドレス空間、または3.99GB、または…を与えるように構成されているので、正確な数はわかりませんが、私が長年見てきたすべてのディストリビューションは構成されています少なくとも3.25GB。


*また、データ用に2GBを完全に取得することもできないことにも注意してください。あなたのプログラム。 OSとそのドライバーがコードにアクセスできるようにするものの大部分は残りの半分にありますが、ロードするすべてのDLLとそれらに必要なスペース、およびその他のさまざまなものとともに、いくつかのビットが半分に残ります。合計が多すぎませんが、ゼロではありません。

37
abarnert