iPhoneバッテリー残量100%が長い理由をLirumデバイス情報で調べる
新しいiPhoneを使用しているとバッテリー残量100%が長続きする気がする。99%->98%よりも100%->99%がやたら長い。Lirumデバイス情報というアプリでバッテリーの状態を調べると、この謎が解明できた。
結論から先に書くと、
- iPhoneのバッテリー実残量は103%や104%の状態がありうる
- 満充電で充電を続けると、充電されない状態に移行する
今回テストしたデバイスは下記の2機種だ。
バッテリーの詳細情報を得るためのアプリはこちら。
アプリを起動して画面左上のボタンを押すとメニューが現れる。 UIの翻訳がひどいので、日本語の時は[Settings]で[English]を選択する方が良い。
バッテリーの状態はメニューから [Tools] -> [Battery] -> [Check Battery Internal Reports]
と進む。
上から順に説明すると
Battery Health 104%: 充電可能容量/端末仕様容量
Battery Wear Level: 上と同じだが、カギカッコ内は100%が上限
Battery is Charging: 充電中はYesとなる。スクリーンショットはケーブルを刺した状態だがNoとなっている。詳細は後述。
Precise Charge: 充電済容量/充電可能容量
注意すべきは、画面右上のバッテリー残量が100%を示していることだ。普段目にするiPhoneのバッテリー残量はどうやらPrecise Chargeの値のようだ。この値の分母はバッテリーの状態で変化する。
Battery Wear Levelの分母は端末の仕様で決まっているバッテリー容量なので固定値、一方、実バッテリー容量は端末仕様より少し多いため100%が長く続くと感じる。ちなみに、手持ちのiPhone XではBattery Healthが103%で、3年以上使ったiPad mini 2は80%だった。
また、最下部のPrecise Chargeが100%となった状態で約1時間程度充電を続けるとBattery is ChargingがYesからNoに変化する。ケーブルが刺さっているのに、バッテリーに給電されていないことになる。どうやらこの状態になると充電が止まった状態でライトニングケーブルからの電源を直接使用してiPhoneが動いているようだ。
最後に注意書き。Lirumデバイス情報はリフレッシュを頻繁にしない場合がある。その場合は画面を遷移させるか、アプリを完全終了(タスク終了)してからアプリを再起動するとバッテリーの最新状態が確認できる。
【PyCUDAでDeep Learningその1】PyCUDAから作るニューラルネットワーク
はじめに
PyCUDAを使ったニューラルネットワーク実装例を示します。Tensorflow, Chainer, KerasなどのDeep LearningライブラリからGPUを使う方法が一般的です。しかし、PyCUDAを使ったGPGPUプログラミングを経験することで、より理解が深まると思います。用いるニューラルネットワークは入力層を含めて3層パーセプトロンの簡易版です。また、MNIST手書き数字の学習および識別を行います。
対象者
- PyCUDAでDeep Learningに入門したい
- PyCUDAによるGPGPUに興味がある
- Deep Learningフレームワークを用いたくない
前提条件
- Python3
- Numpy
- PyCUDA実行環境
Mac使いでPyCUDAの実行環境がまだの人は以下の記事を参考にしてください。
- [PyCUDA環境構築 その1] MacにPython3とNumpyをインストール
- [PyCUDA環境構築 その2] Xcode7とXcode8をインストールして、切り替える方法
- [PyCUDA環境構築 その3] MacにCUDA8をインストール
- [PyCUDA環境構築 その4] PyCUDAをMacOS 10.12 Sierraにインストール
注意事項
ここで用いるニューラルネットワークはかなりテキトーなので、真面目に勉強したい人は他のサイトや書籍を参考にしてください。
- バイアスなし
- 活性化関数はReluのみ
- Softmaxすらない
ネットワークについて詳しくは数式なしでDeep Learning入門1 多層パーセプトロンをご覧ください。
実装
PyCUDA実装の要点
Numpyを用いた実装例は数式なしでDeep Learning入門1 多層パーセプトロンにmlp.pyとして示してあります。ここで示すPyCUDA版と比較してみてください。
PyCUDAでGPGPUプログラミングするときの要点は以下の通りです。
import pycuda.autoinit
linalg.init()
- NumpyのndarrayからPyCUDAのgpuarrayへの変換 一旦Numpyのndarrayを作ってから、gpuarrayに変換します。この際、データ変換と転送が発生します (CPU->GPU)。
w_hid = gpuarray.to_gpu(np.random.rand(n_hid, n_inp).astype(np.float32)/n_inp)
データタイプはfloat32を用いるのが無難です。逆変換 (GPU->CPU)は
w_hid_cpu = w_hid.get()
とするだけです。print()などで結果を表示したり、CPU側で計算したいときはこの処理が必要です。
y = linalg.dot(w, x)
はエラーとなります。
y = lialg.dot(w, x.reshape(2, 1))
とする必要があります。
PyCUDA版の実装例
変数名や関数名のpostfixに「gpu」がついているものはGPU用です。ただし、重みについては付けていません。少しくどくなるからです。
import numpy as np from sklearn.datasets import fetch_mldata from skcuda import linalg from pycuda import gpuarray # GPU初期化 import pycuda.autoinit linalg.init() # ネットワーク定数 n_inp = 784 n_hid = 1024 n_out = 10 # 学習定数 batch = 100 learn_rate = 0.01 update_rate = learn_rate/batch # 重み w_hid = gpuarray.to_gpu(np.random.rand(n_hid, n_inp).astype(np.float32)/n_inp) w_out = gpuarray.to_gpu(np.random.rand(n_out, n_hid).astype(np.float32)/n_hid) dw_hid = gpuarray.to_gpu(np.zeros(w_hid.shape).astype(np.float32)) dw_out = gpuarray.to_gpu(np.zeros(w_out.shape).astype(np.float32)) # MNIST n_train = 60000 mnist = fetch_mldata('MNIST original') data = mnist.data.astype(np.float32) target = mnist.target.astype(np.int32) x_train, x_test = np.split(data, [n_train]) d_train, d_test = np.split(target, [n_train]) n_test = d_test.size # 入力値を0~1に正規化 x_train /= 255 x_test /= 255 # 正解 (GPU) ans_gpu = [] for i in range(n_out): x = np.zeros(n_out).astype(np.float32) x[i] = 1 ans_gpu.append(gpuarray.to_gpu(x).reshape((n_out, 1))) # GPU転置行列 def T_gpu(x_gpu): return linalg.transpose(x_gpu) # GPU内積 def dot_gpu(a_gpu, b_gpu): return linalg.dot(a_gpu, b_gpu) # GPU外積 def outer_gpu(a_gpu, b_gpu): c_gpu = b_gpu.reshape(b_gpu.shape[1], b_gpu.shape[0]) return linalg.mdot(a_gpu, c_gpu) # 誤差微分 def diff_err_gpu(x_gpu, e_gpu): z_gpu = gpuarray.to_gpu(np.zeros(x_gpu.shape).astype(np.float32)) return gpuarray.if_positive(x_gpu > z_gpu, e_gpu, z_gpu) # relu関数 def relu_gpu(x_gpu): z_gpu = gpuarray.to_gpu(np.zeros(x_gpu.shape).astype(np.float32)) return gpuarray.if_positive(x_gpu > z_gpu, x_gpu, z_gpu) # 各層の出力を計算 def output_gpu(x): x_gpu = gpuarray.to_gpu(x).reshape((n_inp, 1)) hid_gpu = relu_gpu(dot_gpu(w_hid, x_gpu)) out_gpu = relu_gpu(dot_gpu(w_out, hid_gpu)) return x_gpu, hid_gpu, out_gpu # 学習していない数字を正しく識別できるか予想 def predict(): score = 0 for i in range(0, n_test): _, hid_gpu, out_gpu = output_gpu(x_test[i]) out = out_gpu.get().reshape(n_out) if d_test[i] == np.argmax(out): score += 1 print('test: {0}%'.format(score / 100)) # 学習用の数字で重みを更新 for epoch in range(1, 2): print('epoch: {0}'.format(epoch)) # ランダムな順序に学習 perm = np.random.permutation(n_train) # 100個単位で学習 for i in range(0, n_train, batch): x_batch = x_train[perm[i:i+batch]] d_batch = d_train[perm[i:i+batch]] # 学習データを100個みせる for j in range(batch): x_gpu, hid_gpu, out_gpu = output_gpu(x_batch[j]) # 誤差計算 e_out = ans_gpu[d_batch[j]] - out_gpu e_hid = T_gpu(dot_gpu(T_gpu(e_out), w_out)) e_hid = diff_err_gpu(hid_gpu, e_hid) dw_out += outer_gpu(e_out, hid_gpu) dw_hid += outer_gpu(e_hid, x_gpu) # 100個みせたので重み更新 w_out += dw_out * update_rate w_hid += dw_hid * update_rate dw_out *= 0.9 dw_hid *= 0.9 # 学習が進んでいるか1000個ごとに識別予想 if (i%1000) == 0: predict()
結果
基本的にはCPU版のmlp.pyの時と同等の結果が得られました。
epoch: 1 test: 9.8% test: 17.06% test: 10.2% test: 10.2% test: 24.61% test: 41.79% test: 42.53% test: 60.8% test: 59.03% test: 59.77% test: 62.69% ... epoch: 10 test: 96.89% test: 96.96% test: 96.87% test: 96.93% test: 96.87% test: 96.98% test: 96.98% test: 96.92% test: 96.97% test: 97.02% test: 97.05%
使用したマシンは以下の通りです。
- MacBook Pro, 2014 Mid
- MacOS Sierra 10.12.6
- Core i7 2.8GHz/16GBメモリ
- NVIDIA GeForce GT 750M 2GB GDDR5
- Xcode 7.3.1 & Command Line Tools
次にパフォーマンスについて調べてみます。
CPU v.s. GPU
ここでは、CPU版のmlp.pyとGPU版のmlp_gpu.pyを速度比較してみましょう。時間がかかるので、epoch数は1とします。
for epoch in range(1, 11):
を
for epoch in range(1, 2):
と変更してください。
また、最後のpredict()をコメントアウトして、学習時間だけを計測します。
#if (i%1000) == 0: #predict()
$ time python3 mlp.py ... $ time python3 mlp_gpu.py
で計測します。
1 epoch, 学習のみ
- CPU/mlp.py
n_hid=64, 0m5.363s n_hid=1024, 1m12.998s n_hid=4096, 4m17.055s n_hid=8192, 11m52.893s
n_hid=64, 1m38.650s n_hid=1024, 4m17.613s n_hid=4096, 5m6.054s n_hid=8192, 7m17.181s
ニューロン数が少ないとCPU演算の方が高速なことがわかります。むやみやたらとGPUを用いるとかえってパフォーマンスが落ちます。3層の単純なニューラルネットワークでは隠れ層のニューロンを多くしても今回の課題に対して良い結果をもたらしません。このようなケースではCPU演算で十分です。
入力データであるMNIST(具体的にはx_testとx_train)を事前にgpuarrayに変換して保持することで、多少のパフォーマンス改善が得られます。興味のある方は試してみてください。
おすすめ書籍
数式なしでDeep Learning入門1 多層パーセプトロン
はじめに
対象者
この記事はDeep Learningの基礎を勉強してみたが、すぐに挫折したという方が対象です。
- 数式を使用しないでニューラルネットワークを理解した気になりたい
- 厳密な説明よりもわかった気になりたい
- なるべく単純なニューロンとニューラルネットワーク (入力層+隠れ層+出力層)で理解したい
- 簡潔なPythonスクリプトで実装したい
前提条件
Python3とNumpyが使える
注意事項
ここで紹介しているニューラルネットワークは何かと簡略化されています。ちゃんと勉強したい人は他のサイトも参考にしてください。一般的でない事項を列挙します。
理論
多層パーセプトロン (MLP: Multi Layer Perceptron)
まず、パーセプトロンの説明から。パーセプトロンは入力に重みをかけた値を全部足します。足した値が0より大きいとその値を出力します。そうでない場合は0を出力します。これをPythonで表現すると
import numpy as np x = np.array([0, 1, 1]).astype(np.float32) w = np.random.rand(3, 3).astype(np.float32) y = np.maximum(0, np.dot(w, x))
パーセプトロンを複数用意して各層をつなぎます。これが多層パーセプトロンです。パーセプトロンは神経細胞の振る舞いを単純化していて「ニューロン」とも呼ばれます。以下では単にニューロンと呼びます。
ニューロンの振る舞いを「投票」のようにも解釈することができます。入力を全部足して出力を決定するからです。ただし入力に重みをかけるため、「投票」される一票は平等ではありません。入力の大きさを「声の大きさ」、一票の重みを「信頼度」と解釈してみましょう。ニューロンはつながっている他のニューロンの声の大きさに信頼度を上乗せして、自身の声の大きさを決めます。
以下では、入力の大きさを「声」、重みを「信頼」と置き換えて説明していきます。
学習方法: 誤差逆伝播法 (Back Propagation)
次に学習についてです。学習とは「信頼」を調整することです。正解との「ずれ」があるとそのぶん「信頼」を「上げたり」「下げたり」します。われわれ人間社会でも同じことを日常的にしているかもしれません。
「信頼」の調整は、正解との「ずれ」すなわち出力層の誤差をもとに行われます。出力層から入力層に向けて誤差が伝わるので、誤差逆伝播という名前がついています。
出力層のあるニューロンの正解が1とします。実際の計算結果が0.3とします。誤差は0.7となります。このニューロンはもっと大きく反応すべきです。そのためには「信頼」を大きくする必要があります。ではどの程度「信頼」を修正すれば良いのでしょうか?まず、誤差が大きいと修正量もまた大きくなります。さらに「信頼」が大きいほど修正量も大きくなります。
Pythonで実装します。正解をans、出力層の誤差をe_out、隠れ層の誤差をe_hidとします。
ans = np.array([1, 0, 0]).astype(np.float32) e_out = ans - y_out e_hid = np.dot(e_out, w_out) * (y_hid > 0)
y_hidとy_outはそれぞれ隠れ層と出力層の出力です。
前層の影響は「信頼」と「声」で決まりました。そこで、「信頼」が大きいものほど誤差に寄与したと考えます。np.dot(w_out.T, e_out)がこれに相当します。ただし、「声」が0の場合は誤差に貢献していなので、(y_hid > 0)をかけています。
続いて「声」の影響を考慮します。単純に誤差に「声」をかけるだけです。これで入ってきた「声」に応じて修正量が大きくなります。出力層と隠れ層の「信頼」の変化量をそれぞれdw_outとdw_hidとします。また、「声」をinpとします。
dw_out += np.outer(e_out, y_hid) dw_hid += np.outer(e_hid, inp)
dw_outとdw_hidの初期値はどちらも0です。
学習は「信頼」を少しづつ変化させることで進めます。
w_out += dw_out * 0.01 w_hid += dw_hid * 0.01
0.01を学習率と呼びます。
学習は繰り返し行われます。全種類の「声」をネットワークに見せることを1 epochと呼びます。20回なら20 epochです。先人の知恵でepochごとの重み変化に0.9をかけて足すことで、学習が上手くいくことがわかっています。そこで、1 epochごとに
dw_out = dw_out*0.9 dw_hid = dw_hid*0.9
とします。0.9をモーメンタムと呼びます。
バッチ学習
ニューラルネットワークを学習させるには学習用のデータとテスト用のデータを必ず分ける必要があります。テスト用のデータを用いて学習することは決して行ってはいけません。ネットワークの性能をテスト用のデータを用いて計ります。
バッチ学習とは学習用のデータをある程度まとめてネットワークに「みせる」(入力する)ことです。100個程度まとめることが一般的なようです。手書き数字による実装例では学習用のデータを100個みせて重みを更新することを繰り返します。
実装例
MNIST
MNISTは28x28ピクセルの0~9の手書きデータです。中には「a」にしか見えない「2」があったりします。入力層のニューロン数は28x28=784となります。MNISTを使用するにはsklearnをインストールします。
sklearn Installation
$ pip3 install sklearn
sklearn Download
$ python3 >>> from sklearn.datasets import fetch_mldata >>> mnist = fetch_mldata('MNIST original')
初めての場合、ダウンロードが始まるので結構時間がかかります。ホームディレクトリのscikit_learn_data/mldata/mnist-original.matがデータの実体です。
mlp.py
いよいよ実装です。python3用のスクリプトです。入力層は784個でした。隠れ層はとりあえず64個とします。出力層は0から9の数字を識別するので10個とします。
正解の配列をあらかじめ作っておく方式に変更しました。
import numpy as np from sklearn.datasets import fetch_mldata # ネットワーク定数 n_inp = 784 n_hid = 64 n_out = 10 # 学習定数 batch = 100 learn_rate = 0.01 # 重み w_hid = np.random.rand(n_hid, n_inp).astype(np.float32)/n_inp w_out = np.random.rand(n_out, n_hid).astype(np.float32)/n_hid dw_hid = np.zeros(w_hid.shape).astype(np.float32) dw_out = np.zeros(w_out.shape).astype(np.float32) # MNIST n_train = 60000 mnist = fetch_mldata('MNIST original') data = mnist.data.astype(np.float32) target = mnist.target.astype(np.int32) x_train, x_test = np.split(data, [n_train]) d_train, d_test = np.split(target, [n_train]) n_test = d_test.size # 入力値を0~1に正規化 x_train /= 255 x_test /= 255 # 正解配列 ans = [] for i in range(n_out): x = np.zeros(n_out).astype(np.float32) x[i] = 1 ans.append(x) # 各層の出力を計算 def output(x): y_hid = np.maximum(0, np.dot(w_hid, x)) y_out = np.maximum(0, np.dot(w_out, y_hid)) return y_hid, y_out # 学習していない数字を正しく識別できるか予想 def predict(): score = 0 for i in range(0, n_test): inp = x_test[i] y_hid, y_out = output(inp) if d_test[i] == np.argmax(y_out): score += 1 print('test: {0}%'.format(score / 100)) # 学習用の数字で重みを更新 for epoch in range(1, 11): print('epoch: {0}'.format(epoch)) # ランダムな順序に学習 perm = np.random.permutation(n_train) # 100個単位で学習 for i in range(0, n_train, batch): x_batch = x_train[perm[i:i+batch]] d_batch = d_train[perm[i:i+batch]] # 学習データを100個みせる for j in range(batch): inp = x_batch[j] y_hid, y_out = output(inp) # 誤差計算 e_out = ans[d_batch[j]] - y_out e_hid = np.dot(e_out, w_out)*(y_hid > 0) dw_out += np.outer(e_out, y_hid) dw_hid += np.outer(e_hid, inp) # 100個みせたので重み更新 w_out += dw_out * learn_rate / batch w_hid += dw_hid * learn_rate / batch dw_out *= 0.9 dw_hid *= 0.9 # 学習が進んでいるか1000個ごとに識別予想 if (i%1000) == 0: predict()
実行結果
$ python3 mlp.py epoch: 1 test: 10.28% test: 10.32% test: 10.32% test: 10.66% test: 26.44% test: 35.07% test: 44.5% test: 58.98% test: 64.65% ... epoch: 10 test: 97.03% test: 96.96% test: 97.03% test: 97.06%
学習が進むにつれ、正解率が上がっていきます。10 epoch程度で97%の正解率が得られました。
さいごに
mlp.pyにはいくつかパラメーターがあります。色々いじってみると理解が深まります。
- n_hid: 隠れ層のニューロン数を16とか128にしてみる
- learn_rate: 学習率を0.1とか0.001にしてみる
- 重みを初期化する際に入力数で割るのではなく、np.sqrt(入力数)で割ってみる
冒頭で申し上げた通り、ここで紹介したニューラルネットワークはテキトーです。なんとなくわかった気になったら、他のサイトや書籍できちんと勉強してください。この記事がディープラーニング入門の手助けになれば幸いです。
おすすめ書籍
【PyCUDA環境構築その4】 PyCUDAをMacOS 10.12 Sierraにインストール
この記事は、PyCUDAでDeep LearningをするためのMac環境構築その4です。PyCUDAをMacにインストールする手順を説明します。
前提条件は以下の通りです。
上述でインストールがまだのものがありましたら、下記の記事リストからインストールしてください。
記事リスト
以下のリンクから各記事に飛ぶことができます。
[PyCUDA環境構築 その1] MacにPython3とNumpyをインストール
[PyCUDA環境構築 その2] Xcode7とXcode8をインストールして、切り替える方法
[PyCUDA環境構築 その3] MacにCUDA8をインストール
[PyCUDA環境構築 その4] この記事
開発環境
使用したMacのスペックは以下の通り。
Macbook Pro, 2014 Mid
MacOS Sierra 10.12.6
Core i7 2.8GHz/16GBメモリ
NVIDIA GeForce GT 750M 2GB GDDR5
Xcode 7.3.1 & Command Line Tools
(Xcode 8.xはCUDA8が対応していません)
DYLD_LIBRARY_PATHとPATHを設定
.bashrcに追加します。
export DYLD_LIBRARY_PATH=/usr/local/cuda/lib:/Developer/NVIDIA/CUDA-8.0/lib:$DYLD_LIBRARY_PATH export PATH=/Developer/NVIDIA/CUDA-8.0/bin:$PATH
変更内容を反映。
# source .bashrc
常にNVIDIA GeForceを使用するように設定
Macbook Proには省電力のためにGPUが自動で切り替わるモデルがあります。常にNVIDIAのGPUが使われるように設定を変更します。
[システム環境設定]-[省エネルギー]-[グラフィックスの自動切り替え]をオフ
Xcode7に切り替え
CUDA8はXcode8に対応していません。Xcode7.x (執筆時Xcode7.3.1が最新)およびCommand Line Toolsが必要となります。Xcode8とXcode7をインストールしている場合は、xcode-selectコマンドでXcode7に切り替えます。
PyCUDAのインストール
# pip3 install pycuda
PyCUDAの確認
# python3 -c "import pycuda.autoinit
scikit-cuda (skcuda)をインストール
# pip3 install scikit-cuda
テストスクリプトで動作確認
import pycuda.autoinit import pycuda.driver as cuda from pycuda import gpuarray from skcuda import linalg import numpy as np linalg.init() a = np.random.rand(2, 1).astype(np.float32) b = np.ones(2).astype(np.float32).reshape(1, 2) a_gpu = gpuarray.to_gpu(a) b_gpu = gpuarray.to_gpu(b) c_gpu = linalg.dot(a_gpu, b_gpu) c = c_gpu.get() print(a) print(b) # 内積をCPUで計算した結果 print(np.dot(a, b)) # 内積をGPUで計算した結果 print(c)
上のスクリプトをtest_gpu.pyとして保存して実行します。
# python3 test_gpu.py [[ 0.85600704] [ 0.02441464]] [[ 1. 1.]] [[ 0.85600704 0.85600704] [ 0.02441464 0.02441464]] [[ 0.85600704 0.85600704] [ 0.02441464 0.02441464]]
テストスクリプトtest_gpu.pyを説明します。
PythonでGPUを利用するための初期化処理等の準備をします。
import pycuda.autoinit
...
linalg.init()
GPUで処理する前に一旦Numpyのndarrayを作ります。データタイプはfloat32を使用します。
a = random.rand(2, 1).astype(np.float32) b = np.ones(2).astype(np.float32).reshape(1, 2)
次にndarrayをgpuarrayに変換します。
a_gpu = gpuarray.to_gpu(a) b_gpu = gpuarray.to_gpu(b)
この処理でCPU用のメモリからGPU用のメモリに配列データが変換・転送されます(CPU→GPU)。
c_gpu = linalg.dot(ga, gb)
結果を確認するにはgpuarray (GPU)からndarray (CPU)に戻す必要があります。
c = c_gpu.get()
print(c)
今度はGPU→CPUの流れです。
PyCUDAプログラミングの注意点
PyCUDAを利用したプログラミングでは、CPUとGPUを行き来するため、変数がndarrayかgpuarrayかを常に意識することが重要です。また、CPU/GPU間のデータ変換はパフォーマンスに大きな影響を与えるため、最小限に止めることが望ましいです。
便利な関数
gpuarrayとlinalgには下記のような便利な関数があります。
- linalg.dot(x, y): 内積
- linalg.transpose(x): 転置行列
- gpuarray.max(x): 最大値
- abs(x): 絶対値
- x.shape: ndarrayのshapeと同じ
- gpuarray.if_positive(x > z, x, z): zが0ならrelu
ただし、xをgpuarrayとします。
APIドキュメントリンク
GPU Arrays — PyCUDA 2017.1.1 documentation
skcuda.linalg.dot — scikit-cuda 0.5.2 documentation
関連書籍
Python Parallel Programming Cookbook
洋書だがPyCUDAについて解説した数少ない書籍。PyCUDAについて約50ページが割かれている。
はじめてのCUDAプログラミング―驚異の開発環境[GPU+CUDA]を使いこなす! (I・O BOOKS)
CUDAの入門におすすめ。初心者にわかりやすいと定評がある。
CUDA C プロフェッショナル プログラミング (impress top gear)
CUDA中〜上級者におすすめ。マルチGPUについての解説あり。
関連記事
以下のリンクから各記事に飛ぶことができます。
[PyCUDA環境構築 その1] MacにPython3とNumpyをインストール
[PyCUDA環境構築 その2] Xcode7とXcode8をインストールして、切り替える方法
[PyCUDA環境構築 その3] MacにCUDA8をインストール
[PyCUDA環境構築 その4] この記事
【PyCUDA環境構築その3】 MacにCUDA8をインストール
注意 この記事はNVIDIA製GPUを搭載していないMacbookは対象外です。
Macbook ProにCUDA8.0をインストールする手順を説明します。CUDAはNVIDIAが提供するGPGPUのためのライブラリ、コンパイルなどの統合開発環境です。要はNVIDIA製のGPUを使って並列計算するためのツール群です。
この記事は、PyCUDAでDeep LearningをするためのMac環境構築その3です。PyCUDAがCUDAを必要とするためCUDA8.0をインストールします。
記事リスト
以下のリンクから各記事に飛ぶことができます。
[PyCUDA環境構築 その1] MacにPython3/Numpy/Scipyをインストール
[PyCUDA環境構築 その2] Xcode7とXcode8をインストールして、切り替える方法
[PyCUDA環境構築 その3] この記事
[PyCUDA環境構築 その4] PyCUDAをMacOS 10.12 Sierraにインストール
開発環境
使用したMacbook Proのスペックは以下の通り。
Macbook Pro, 2014 Mid
MacOS Sierra 10.12.6
Core i7 2.8GHz/16GBメモリ
NVIDIA GeForce GT 750M 2GB GDDR5
Xcode 8.3.2 & Command Line Tools
Xcode 7.3.1 & Command Line Tools
CUDAをダウンロード及びインストール
CUDA Toolkit Download | NVIDIA DeveloperからOS、バージョンを選んでパッケージをダウンロードします。インストーラーの指示通りインストールします。
CUDAをアップデート
MacOSのシステム環境設定からCUDAを選んでInstall CUDA Updateをクリック
cudnnをインストール
NVIDIA cuDNN | NVIDIA Developerからcudnnをダウンロードします。メンバー登録が必要な場合があります。
ダウンロードしたcudnn-8.0-osx-x64-v6.0.tgzを解凍します。
# tar zxvf cudnn-8.0-osx-x64-v6.0.tgz
ファイルをシステムにデプロイします。
# sudo mv <解凍フォルダ>/lib/libcudnn* /usr/local/cuda/lib # sudo mv <解凍フォルダ>/include/cudnn.h /usr/local/cuda/include
DYLD_LIBRARY_PATHとPATHを設定
.bashrcに追加します。
export DYLD_LIBRARY_PATH=/usr/local/cuda/lib:/Developer/NVIDIA/CUDA-8.0/lib:$DYLD_LIBRARY_PATH export PATH=/Developer/NVIDIA/CUDA-8.0/bin:$PATH
変更内容を反映。
# source .bashrc
常にNVIDIA GeForceを使用するように設定
Macbook Proには省電力のためにGPUが自動で切り替わるモデルがあります。常にNVIDIAのGPUが使われるように設定を変更します。
[システム環境設定]-[省エネルギー]-[グラフィックスの自動切り替え]をオフ
Xcode7に切り替え
CUDA8はXcode8に対応していません。Xcode7.x (執筆時Xcode7.3.1が最新)およびCommand Line Toolsが必要となります。Xcode8とXcode7をインストールしている場合は、xcode-selectコマンドでXcode7に切り替えます。わからない場合は、下のエントリーを参考にしてください。
CUDAサンプルプログラム
サンプルプログラムでインストールを確認できます。ただしコンパイルに時間が結構かかります。
# /Developer/NVIDIA/CUDA-8.0/bin/cuda-install-samples-8.0.sh ~/Downloads # cd ~/Downloads # make -C 1_Utilities/deviceQuery # 1_Utilities/deviceQuery/deviceQuery # make -C 5_Simulations/smokeParticles # 5_Simulations/smokeParticles/smokeParticles
コンパイルエラーが出る場合は、Xcodeの切り替え、DYLD_LIBRARY_PATHとPATHの設定、省エネルギーの設定を疑ってみてください。
【PyCUDA環境構築その2】 Xcode7とXcode8をインストールして、切り替える方法
Xcode7.xとXcode8.xを共存させる方法を紹介します。
この記事は、PyCUDAでDeep LearningをするためのMac環境構築その2です。PyCUDAはCUDAに依存しています。CUDAはXcode8に対応しておらず、Xcode7をインストールする必要があります。
記事リスト
以下のリンクから各記事に飛ぶことができます。
[PyCUDA環境構築 その1] MacにPython3とNumpyをインストール
[PyCUDA環境構築 その2] この記事
[PyCUDA環境構築 その3] MacにCUDA8をインストール
[PyCUDA環境構築 その4] PyCUDAをMacOS 10.12 Sierraにインストール
Xcode 8.xのインストール
MacOSのApp StoreからXcodeをインストールします。
ターミナルを開いて、
# sudo mv /Applications/Xcode.app /Applications/Xcode8.app
Xcode 7.xのインストール
記事執筆時ではXcode 7.3.1がXcode7では最新でした。Downloads for Apple Developer からSee more downloadsを選んで、検索ボックスに「Xcode 7」と入力します。Xcode 7.3.1とCommand Line Tools for Xcode 7.3.1をダウンロードします。
ダウンロードしたdmgファイルを開いてXcode 7.3.1をインストールします。続いてCommand Line Tools for Xcode7.3.1もインストールします。
ターミナルを開いて、
# sudo xcode-select -s /Applications/Xcode.app
次にCommand Line Toolsのdmgを開いてをインストールします。
Xcodeの切り替え
上述の手順通り進めていたら、Xcode7がアクティブになっています。Xcode8に切り替えるには、
# sudo mv /Applications/Xcode.app /Applications/Xcode7.app # sudo mv /Applications/Xcode8.app /Applications/Xcode.app # sudo xcode-select -s /Applications/Xcode.app
Xcode7に切り替えるには
# sudo mv /Applications/Xcode.app /Applications/Xcode8.app # sudo mv /Applications/Xcode7.app /Applications/Xcode.app # sudo xcode-select -s /Applications/Xcode.app