56208


Twitter で `isOdd` 関数を switch-case
で実装する効率の悪い例が[バズっていました](https://twitter.com/NAGAYASU_Shinya/status/1143868066440216577)。この例では
1 から 10000 まで書いていましたが、僕はこれを INT_MIN から INT_MAX まで case
を書けば確かに動作するなと（冗談で）思いました。

そこで、INT_MIN から INT_MAX まで case で分岐する C 言語のプログラムを出力するプログラムを書き実行したところ、108 GB
のプログラムファイルを得ました。

ここまでは良かったのですが、この巨大なプログラムを gcc でコンパイルしようとしたところ、以下のように `out of memory` エラーが出ました。

[code]

    $ ls -lah calc.c
    -rwxrwxrwx 1 nek nek 108G Jun 28 06:10 calc.c
    $ gcc -Wall -Wextra -o calc calc.c
    
    cc1: out of memory allocating 115889378580 bytes after a total of 475136 bytes
    
[/code]

`free` コマンドで確認してみたところ、なるほど確かにメモリ（とスワップ領域）が足りないようです。115889378580 bytes ≒ 116 GB
です。

[code]

    $ free -h
                  total        used        free      shared  buff/cache   available
    Mem:            15G        6.8G        8.9G         17M        223M        9.0G
    Swap:           48G        100M         47G
    
[/code]

エラーメッセージで検索したところ、`swapon`
で[一時的にスワップ領域を増やす方法を見つけました](https://stackoverflow.com/a/11289081/5989200)。これを試してみたのですが、いまこれを実行していたのが
WSL であり、どうやら WSL では `swapon` が実装されていないため、スワップ領域を増やすことができませんでした。

[code]

    $ swapon tmpswap
    swapon: /mnt/c/(中略)/tmpswap: insecure permissions 0777, 0600 suggested.
    swapon: /mnt/c/(中略)/tmpswap: insecure file owner 1000, 0 (root) suggested.
    swapon: /mnt/c/(中略)/tmpswap: swapon failed: Function not implemented
    
[/code]

さて、では WSL 上でこの巨大なプログラムをコンパイルするための領域を確保するにはどうすれば良いでしょうか？ `swapon`
以外に何か方法はありませんでしょうか。

※Windows 上の mingw-w64 を使う方法もありそうですが、ひとまず WSL 上でコンパイルできないか考えています。

### 環境

  * Windows 10 Home, Version 1803, Build 17134.829
  * Windows Subsystem for Linux (WSL 1) の Ubuntu 18.04.2
  * gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0


CC BY-SA 4.0
2019-06-28T16:46:48.367
56201
2019-06-29T01:52:28.980
19110
question
linux ubuntu gcc wsl スワップ
WSL 1で大量のメモリを確保する方法


公式の資料を見つけられませんが、下記issueにある開発メンバーのコメントを読む限り、どうやら、WSL1はWindows側の物理メモリとページングファイルをそのまま使用するらしく、`free`でもそれらのサイズをそのまま表示しているだけのようです。

<https://github.com/Microsoft/WSL/issues/92#issuecomment-222318797>

注意して欲しいのは、Windowsのシステムのプロパティにある仮想メモリのページングファイルサイズ、タスクマネージャーのコミット済みのサイズ(仮想メモリのサイズ)、`systeminfo`で表示される仮想メモリのサイズ等は、
**現在割り当てられているページングファイルのサイズ** から算出されていることです。対して、`free`で表示されるSwapは
**ページングファイルに割当可能な最大サイズ**
のようで、Windows上での表示のサイズとは異なります。システムで自動的に管理している場合、割り当てが可能な最大サイズをWindows上で表示させる方法は見つけられませんでした。  
※ Windows上での「仮想メモリ」の表現は物理メモリ+ページングファイルであることに注意してください。

実際に最大サイズを確認して、一致するかどうか見てみました。私の環境(Windows 10 1903)では次のようになっています。

[code]

    $ free
                  total        used        free      shared  buff/cache   available
    Mem:       33471164    11745580    21496232       17720      229352    21591852
    Swap:      60856004      316168    60539836
    
[/code]

テストには[Testlimit](https://docs.microsoft.com/en-
us/sysinternals/downloads/testlimit)を使用しました。100,000MiBを割り当てようとしたとき、71,598MiBで割当失敗が報告されはじめ(しかも、Chromeが落ちて、書きかけのこの回答が消えたと思って焦る)、その時のタスクマネージャー上でのコミットサイズが最大で約90GiBでした。このサイズは`free`でのMemとSwapの合計と一致します。  
※ Windows上での表記は「MB」や「GB」ですが、実際は2進数接頭辞で計算されています。  
※
使用量の合計容量があっていませんが、`free`を実行後に、Timelimitを探したり、色々していたので、Chrome等のメモリ使用量が増えていたのだと思われます。

とりあえず、Windows側の仮想メモリのページングファイルのサイズを増やしたら、増えると思われます。試して見てください。

【変更方法】  
「設定」->「システム」->左メニュー「バージョン情報」->関連設定の「システム情報」->左メニュー「システムの詳細設定」->タブ「詳細設定」->パフォーマンスの「詳細設定」->タブ「詳細設定」->仮想メモリの「変更」->「すべてのドライブのページングファイルのサイズを自動的に管理する」のチェックを外して、カスタマイズして、「OK」


CC BY-SA 4.0
2019-06-29T01:52:28.980
56208
2019-06-29T01:52:28.980
7347
56201
answer