オタク日記
(Mac と Linux, 2015Q4)
目次
2015-12-31 (Thu): お願いしますよ、DoCoMo さん2015-12-25 (Fri): 新プリンタでも躓く
2015-12-22 (Tue): プリンタを新調した
2015-12-09 (Wed): Django Project で Virtual Host
2015-11-12 (Thu): BLAS/LAPACK と Numpy (その 2)
2015-11-11 (Wed): BLAS/LAPACK と Numpy (その 1)
2015-11-04 (Wed): やっぱり Time Machine の実現は難しかった
2015-11-01 (Sun): Raspberry Pi で Netatalk-3
2015-10-31 (Sat): Backup 体制を見直し
2015-10-25 (Sun): 自宅サーバのバッテリを交換
2015-10-21 (Wed): Python/NumPy Update (その 2)
2015-10-18 (Sun): Python/NumPy Update
2015-10-16 (Fri): iPython 再訪
古い日記:
2015Q3
2015Q2
2015Q1
2014Q4
2014Q3
2014Q2
2014Q1
2013Q4
2013Q3
2013Q2
2013Q1
2012 年
2011 年
2010 年
2009 年
2008 年
2007 年
2006 年
2005 年
2004 年
2003 年
2002 年
2001 年
2015-12-31 (Thu): お願いしますよ、DoCoMo さん
SB から DoCoMo へキャリアを変えた時、パケット通信の料金体系も変った。 DoCoMo の「シェアパック 15」というパッケージを導入して、一ヶ月あたり 15GB を家族 4人でシェアしている。 (これは 4 人の転送量の総計が 15GB を超えると、全員に 128 kbps への転送速度制限がかかる、というもの。) 最初は 15GB で足りるかなと、ちょっと心配だったが、 しかし、最近はあまり外出しないし、ましてや MBA を持ち出して tethering する事などは殆どないという事もあり、この制限にひっかかった事はなかった……ところが、帰省の新幹線の中でこれ(帯域制限)を体験する羽目になった。 元々、新幹線の中は接続が不安定なので、 道中のどのあたりでそうなったのかよく分らない。(今思えば、 MBA (Mavericks, Hawk) の Security Update が引き金になったのかも。 何とも無謀な事をやったもんだ。)症状は、FB にアクセスしたら永久に転送が完了しない……、Twitter で RT ができない…… 等々、致命的とまでは行かないけど、イライラさせられる状態が続く。
パケット通信を一番よく使うのが自分で、かつ今月は殆んど使っていない (自宅では WiFi) という思い込みがあり、まさか 15 GB (厳密には、ボーナスパケットを合わせて 20 GB) のリミットをトリップしているとは思いもしなかったので、 なかなか原因が分らなかったが、「ひょっとして」と疑い始めたら、 あっさり「まさにその通り」と判明。 DoCoMo さんの MyDoCoMo の分かり難い藪の中を(しかも 128 kbps で!)うろうろする事数時間で、 確かに「制限にひっかかっている」事、また、 「12月の私の使用量は、 2.2 GB に過ぎず、残りの大半を使っているのは、我が娘である」事等が分った。
それにしても、DoCoMo さんのウェブサイト、分り難いねぇ。キャリアを DoCoMo さんに替えてから、半年近くも MyDoCoMo アカウントさえ作らなかったという自分の怠慢の所為もあるんだろうけど、 上の事柄をすっきり 1 ページに纏めるなんて、そんなに難しい事じゃあなかろうに……
ともあれ、同サイト(の違うページ :-p)で、1 GB を通常速度で転送するオプションを追加購入(1080 円也)して、 ようやく「普通の生活」が復活した。
で、なんやかやで、丸二日程、128 kbps で生活した訣だが、 この体験にはかなり感慨深いものが有った。 以前使っていた ISDN が 64 kbps (後の方では、128 kbps?) なので、 128 kbps と言えばその頃と同程度。実際、「ssh で自宅サーバにログインする」 とか、「同サーバと重要ファイルを rsync で同期する」はたまた、 「同サーバ上のウェブページを表示する」については全く違和感が無い。 (この 10 年間、自宅サーバに殆んど進歩が無かったとも言う。) 問題は、多くの「商用ウェブページ(?)」で、例えば、Facebook, Twitter, Amazon.com/Amazon.co.jp などは、 まともに動いてくれない——ボタンクリックへの応答どころか、 最初のページ表示さえ完了しない事がある。 (何故か Firefox より、Safari の方が応答が良い事を発見した。) 何より「かなわんな」と思ったのは、Emacs/Wanderlust から、gmail.com へ imaps (port: 993) 越しのアクセスが不安定、というかやたら時間がかかるようになる事。
最初は、iPhone6 と MBA 双方の設定を疑い、いろいろ弄ってみたが、 そのうち、USB 接続越しの tethering ができなくなった。 どうやっても、System Preferences > Network で "iPhone USB" を "connected" にできない……。 思い余って、デバイスを一新しようと、"iPhone USB" を一旦削除したら、今度は、新規に "iPhone USB" を add できない(下図のプルダウンメニューで、"iPhone USB" が出てこない。)Mavericks と iOS のリブート、Wi-Fi/Personal Hostspot の ON/OFF とケーブル接続の順序等を散々試してみたが、いずれも効果無し。
Wi-Fi 接続で用は足りるので、一旦は諦めた。1GB 分を買い足して 128 kbps の制限が取れても状況は変わらなかった。が、今度は、iPhone (6) に充電されなくなった……。MBA の USB port に挿しても、iPhone 側に「接続」マークは出るものの、充電されない(残量の % 表示がゆっくり減って行く)——プチ・パニック!
また、iOS/Mavericks の reboot、USB AC アダプタへ替えてみる、等をやっているうちに何時の間にか直った。 つまり、どれが功を奏したのか未詳。やれやれ、と思いつつ、 上記の「デバイス追加」を試みたら、プルダウン・メニューに "iPhone USB" が現れ、それを選択する事で、あっさり USB 越しに Tethering 接続ができた…… (どうやら、MBA の方のドライバがおかしくなっていた、という事のようだ。)
Yosemite 限定かも知れないが、新たに確認した tethering に関する知見のいくつか……
- Wi-Fi/iPhone USB の共存はとっても合理的。Wi-Fi と iPhone-USB のデバイスの両方を add しておくと、どちらか利用可能な方を使って tethering ができる。両方が利用可能だと、USB が優先される(未確認。)
- Wi-Fi
接続の場合、デバイスのインジケータは(緑ではなく)オレンジとなり、
Wi-Fi has the self-assigned IP address 172.20.10.3 and will not be able to connect to the Internet.
等と表示されるが、これで「正常」みたい。
2015-12-25 (Fri): 新プリンタでも躓く
はがき印刷も含めて一応一通りは確認した上で、 「なかなかイケてるかも」と書いたのだが、 実際に宛名書きを始めたら、いきなり問題が……宛名面の右端と下側に 5mm くらいの黒い筋が入る。 つまり「ここぞ、という時にコケて」しまったのだった。使っているアプリは、 「はがきデザインキット」というもの。 去年も使ったけど、こんな問題は無かったし、今年の版(毎年更新される)でも、 裏側(通信面)では問題が出ない……。
こうなると、このアプリとプリンタの「設定」の問題だろうが、 その煩雑さ(整理のされてなさ?)が禍して、なかなか系統的な「カット & トライ」ができない。
Google さんに聞いてみても、それらしい Q&A は見付からない。 ただ、EPSON さんのプリンタについて、「ドライバが Airprint ではなく、CUPS でないとダメ」というのが有った。 元の質問した人が「それでもダメでした」と言ってるし、そもそも EPSON の話だし、 と最初は無視していたのだが、 何時間か他の事をやってみた後「万策尽きた感」が出てきたので、 これを試してみる事にした。
とはいうものの、そもそもプリンタ・ドライバ(のインストーラ)は、 一種類しかないので、少々右往左往したが、 結局ドライバをインストールした後、System Preferences > Printers & Scanners の Add 画面(下記)で、「CUPS 版を使う」とすれば良いらしい (ディフォルトは何故か Airprint.)
これで、何とか「黒枠」の問題は克服できたが、 今度は「郵便番号」の位置が赤枠からかなりずれるようになってしまい、 手で修正する必要があった…… Airprint 版ではこれに関しては問題無かったのになあ。という事で、(根本原因が「はがきデザインキット」側にあるのか、 DCP の方なのかは未詳だが)「なかなかイケてる」は 「使えなくもない」あたりに格下げ。けどまあ、はがきトレーからの紙送りとか、 トレーに紙を補充した後の印刷再開の際とかの「HP プリンタにありがちだった問題」 が皆無だった事は、公平のために付け加えておきたい。
2015-12-22 (Tue): プリンタを新調した
Brother の DCP-J963N というモデルを Amazon から購入した。 なかなか良さげ……さらば HP Printer
もう思い出せない程大昔に最初に買ったプリンタが HP で、それ以降(家族向けのも含めると 5 代くらい?)忠実な顧客だった。 なんでそんなに惚れ込んだのか解らない…… その前の(測定器用の)HPIB のドットインパクト・プリンタが気に入っていたから? 当時としてはドライバに難が少なかった (Macintosh のためのドライバがよくできていた)から? Linux からでも比較的無難に使えたから?…… 今では、もう忘却の彼方だが。とにかく、2 代目だったかの Deskjet 540C は名機だったと思う。ともあれ、(米国で買って使っていた)先代 (Photosmart 3210) は、そこそこ快適に使えた (まあ、 ドライバの更新に関しては色々有ったが :-) なので、5 年近くも使った後でも、日本へ持ち帰ったのだった。 が、対応するインクが日本では買えない事が判明。 型名が違うが全く同型で問題なく装着もできるインクカートリッジが、 プリンタの F/W に弾かれて使えない…… それでは、と、それまで使っていたカートリッジを Amazon.com に注文しようとしたら、日本へは出荷できない、と言われ「怒り心頭」
もう HP なんか二度と買うもんか、と思っていたが、COSTCO に Photosmart 6520 が 4,000 円台で売られていた……なんだか嫌だな、でも、家族向けなら…… と、つい日和ってしまう。設定もスンナリ行って、すぐに使えるようになったが、 しばらくすると「なんだかなぁ」が出てきた。 まず、ウザイと思ったのは (3210 にもその傾向は有ったが) 使おうとすると殆んど毎回、 長々とメンテナンスモードに入る——そうでない場合も、 かなり長いキャリブレーションをやってくれる。 しかし、それよりウンザリさせられたのは、 とにかくインク周りのトラブルが多い事。
- インク残量の表示がおかしいのか、 カートリッジを交換して間もないのに、すぐ Low Ink だと言われる事がある。
- 残量の警告は出てないのに (実際、カートリッジは交換したばかりなのに)全く読めない程、 印刷が薄くなってしまう。
- 純正カートリッジを指してあるのに、「純正でないカートリッジは……」 と文句を言う。(まあ確かに、互換カートリッジを挿した事もあるけどね。)
Brother に……
米国の会社では Brother のモノクロ・レーザープリンタ (HL-L2xxx?) を専有して使っていた。 A4 専用で $150 程度 (?) の廉価版ながら、 なかなか優れもので、コンパクトなのにスタートアップも印刷も速いし、ジャムは皆無……。 難点と言えば、起動の時の音が(とても)うるさい事くらい。この「難点」はオフィスでは我慢できても、home use となると、致命的。 (あとスキャナも欲しいし。)で、HL-シリーズは断念したが、Brother のブランドイメージは相当良くなっていた。
DCP-J963N の WiFi
というわけで、このモデルに決めた。というか、大分前から決めていたのだが、 「first lot は避ける」を実行しているうちに、6520 が「ここぞという時」にコケてくれて、それに背中を押されて、ポチった。 (勿論、そろそろ年賀状を印刷せねば、というのもある……)設定はスムース……と言いたいところだけど、お手の物の筈の WiFi の設定でちょっと引掛った。 実は何が悪いのか解るまでに何時間もかかったのだが、 右往左往をすっとばして結論だけ書くと、 要は「暗証/暗号化方式」のコンパチビリティの問題。 我が家の AP は WPA/WPA2 + TKIP に設定してあり、 これで、iPhone, HP printer, Macintosh, MBA (MacBook Air) 全てで問題なく繋る。 しかし、DCP-J963N はこれに未対応だと主張する……。 接続に失敗すると、何とその都度、詳細をプリントアウトするのだが、 それには、WPA + TKIP, WPA2 + AES をサポートする、 と書いてある。ならば、AP の WPA(/WPA2) + TKIP で OK の筈なのだが……(Brother さん、暗証/暗号化方式の推定のロジックを間違えてないかい?) しかし、まあ、ここで「べき論」を云々しても虚しいので、AP の方を WPA/WPA2 + AES に変えてみたら、あっさり繋がった (Password の再入力さえ不要。)
とは言え、この変更で我が家に 10 個以上ある WiFi デバイスに繋らなくなったら大変——という事で、iPhone, MBA と Mac-mini について確認してみたが、設定を一切弄らなくても AP に接続できた。 とりあえず良かった。
実は、AP の変更に行く前に、AOSS によるペアリングも試みた。AOSS の出始めの頃試してみた事があるが AP とデバイスを近付ける、ってのが面倒で、ずっと使ってなかった。 そもそも、デバイス側の接続方式の推定が優秀になって、「パスワード」(実は「暗号化キー」 だったり「事前共有化キー」だったりする)を入力するだけで済むので、 然程必要無かった、という事もある。だが、今回それがうまく行かず、 よい機会でもあるので久し振りに使ってみた。どうやら AOSS もしっかり進歩しているようで、なんと AP (WZR-HP-AG300H) の制御・設定用ウェブ画面に AOSS のスタートボタンが有る!おかげで、AP と物理的に近付けなくてすんだ。しかし「AP 本体のボタンを同時に押す」のが、 セキュリティ確保の眼目だった筈なんだけどこれでええんやろか? :-)
とにかくかくにも繋ったのはとても有難いが、AOSS 専用の SSID が増設されたりして、 気色が悪い(家内 DDNS との干渉が心配。)なので、 程なく AOSS は disable したが、一旦繋ったおかげで、注意が AP の「暗号化方式」の設定に注意が向いたのだった。
第一印象
まだ、三日程しか使ってないが、とりあえずの印象を……- とにかく可用性が高い。スリープモードから、プリント、スキャン、コピー、 いずれも数秒でスタートする。特に、コンピュータ (Mac) から、制御する場合も、WiFi の再接続に時間が全くかからないのが嬉しい。 (対して HP Photosmart は、メンテナンスモードに入らない場合でも、 何かキャリブレーションでもしているのか、ガーガーガリガリ と音を立て、数十秒は待たされる。)
- LCD の表示は明るくてクリア。 が、メニューはお世辞にもよく整理されているとは言えない。特に、WiFi のインジケータが、設定開始のボタンになっているのは「何だかなぁ」だった。 (まあ、慣れてしまえば何でもないけど、 でも最初に設定してしまったら、この機能を使う必要もない訣で……)
- (今回は WiFi 一本で行く予定なので、問題にならないが)USB と Ethernet のレセプタクルが、本体の奥深くにある。 これは、上記のモノクロ・レーザープリンタ (LH-L2xxx) の時からこうだった……。 その時は「ネットワーク対応モデルとそうでないのとの間で、 筐体の金型を共有するために違いない」などと邪推したものだが、もう 5 年も経つのにそのまま、とは……
- 動作音が結構うるさい。これも、LH-L2xxx からの伝統 :-) ひょっとすると、本体を目の前に置いて試用しているせいかも知れないが……
- AFD が素晴しい。ドライバの "Continuous Scanning" オプションと相俟って、複数枚の原稿を、multi-page の pdf にしてくれる。 これは嬉しい。主目的が既存の紙原稿のスキャニングだから、これだけでも、 (少々値が張る)本モデルを選んだ甲斐が有ったと言うもの。
2015-12-09 (Wed): Django Project で Virtual Host
Mod_wsgi の進化
前述のように、既に一年前に Ubuntu-14.04 LTS で mod_wsgi を使い始めたのだった。 この時、使った mod_wsgi は -3.4 で、libapache2-mod-wsgi-py3 (3.4-4ubuntu2)
という deb package で供給されたものだった。
-3.4 は 2012-08 にリリースされているので、二年以上経っていて、
もう開発は終っているのか、と思われた。
が、何と今や mod_wsgi
はPyPI
(Python の module package index)
に入っていて、そちらではもう -4.4.x にまで上っている。Apache の module
が PyPI
に入っている、というのもさる事ながら、それを「Python に Install
する」(Installation into Python) というあたりにも大いに面喰った。
が、なんとかインストールでき、使い始める事ができたのだった。
しかし、これは Virtual Host になってない、つまり、 mod_wsgi-express を走らせて、httpd.conf を作った Django Project しかカバーできない。今回のお題を一言で言えば「これを何とかしたい」 すなわち「最新の mod_wsgi と Virtual Host で、複数の PyVenv 上の Django Project を公開できるようにする事」となるだろう。(こう書いてしまうと、 つぎ込んだ時間の割にあまりにも「ささやか」な目標になってしまうので、ちょっと寂しい :-))
Ubuntu-16.04 LTS と pyvenv
Ubuntu はコマンド群のバージョンアップに比較的迅速に追随してくれるが、 偶には、(例えば Netatalk のように)「何年も放置」なんて事もある。 今回の mod_wsgi も、最新版(4.4 以降)が deb package になってくれれば、 諸々の事が簡素かつ安定になるのだが…… という事で、来年春の正式リリースまでに相当多数の更新が有ると期待される 16.04 をインストールしておこうと思い立ったのだった。 (あわよくば、Netatalk も mod_wsgi も最新になるのではないかと…… :-)まだ β 版でもないようなので、ちょっと心配だったが、 インストールには何も問題が無かった。 インストールの後、ほぼ毎日猛烈な勢いでパッケージが更新されていくが、 残念ながら今のところ、Netatalk も mod_wsgi も古いままである。 (ちなみに systemd への移行もまだ中途半端。)
しかし、リブートは滅茶苦茶速い。Mac-mini のストレージが(Fusion drive のせいで)速くなっている、という事もあるだろうが、Ubuntu 側の改善もあるに違いない。 (15.04 が約 10 秒かかるのに対し、16.04 は 6-7 秒!)
インストール・メモ:
- xenial-desktop-amd64.iso (1.2GB) をダウンロード(約 18分)
- VMware Fusion の VM に easy install で、install (約 5分)
- 一旦シャットダウンして、VM の設定を変更: CPU/Memory: 2 core/2GB, Network: Bridge.
- boot して、追加の設定: timezone, hostname を設定(hostname は /etc/hostname を編集する)
- 追加のパッケージをインストール
fukuda@xenial:~$ sudo apt-get install ssh emacs lv fukuda@xenial:~$ sudo apt-get install python3.4-dev apache2-dev git fukuda@xenial:~$ sudo apt-get install python3.5-dev python3.5-venv fukuda@xenial:~$ sudo apt-get build-dep mod-wsgi fukuda@xenial:~$ sudo apt-get build-dep matplotlib
- pyvenv を構築。
fukuda@xenial:~$ pvenv-3.5 pve35 fukuda@xenial:~$ cd pve35/ fukuda@xenial:~/pve35$ . bin/activate (pve35) fukuda@xenial:~/pve35$ (pve35) fukuda@xenial:~/pve35$ pip install --upgrade pip (pve35) fukuda@xenial:~/pve35$ emacs -nw requirements.in (pve35) fukuda@xenial:~/pve35$ cat requirements.in django==1.8.7 mod_wsgi django-timezone-field matplotlib (pve35) fukuda@xenial:~/pve35$ pip-compile (pve35) fukuda@xenial:~/pve35$ pip-sync (pve35) fukuda@xenial:~/pve35$ pip freeze | grep mod-wsgi mod-wsgi==4.4.21
試験用ネットワーク環境を作る
上記のように、既に Ubuntu のディフォルトの設定で、DHCP で、xenial という hostname にその時空いている IP address の一つがアサインされるようになっている(以下仮にこれを '192.169.0.119' とする。) Virtual Host の設定を試験するために、この IP をもつ hostname を設定する——勿論 DDNS (= dhcpd + bind9) が走っているホスト (Lark)上で実行。fukuda@lark:/var/cache/bind% sudo nsupdate -d -k /etc/bind/rndc.key Creating key... Creating key... namefromtext keycreate > update add xenial1.otacky.jp 3600 IN A 192.168.0.119 > send > update add xenial2.otacky.jp. 3600 IN A 192.168.0.119 > send fukuda@lark:/var/cache/bind% dig xenial2.otacky.jp .... ;; ANSWER SECTION: xenial2.otacky.jp. 3600 IN A 192.168.0.119これでは勿論、xenial にアサインされる IP address が変わったらうまく行かなくなり、とてもスマートとは言えないが、 とりあえずの試験用としては使えるだろう。(ここでは CNAME は使えない。)
構想としては
- 'xenial.otacky.jp' ⇒ 'Taka's Home Page': www.otacky.jp のコピー(CGI を若干含む)
- 'xenial1.otacky.jp' ⇒ 'wrm_tts': Django Project (その 1)
- 'xenial2.otacky.jp' ⇒ 'net_tts': Django Project (その 2)
Django Project を種々のサーバで公開してみる
まずはテスト用の Django Project (上の 「その 1」) を git:(pve35) fukuda@xenial:~/pve35$ git clone git://otacky.jp/wrm_tts.git (pve35) fukuda@xenial:~/pve35$ ls wrm_tts -l total 43220 -rw-rw-r-- 1 fukuda www-data 44234752 Dec 8 14:48 db.sqlite3 drwxrwxr-x 4 fukuda fukuda 4096 Dec 6 10:16 htdocs -rwxrwxr-x 1 fukuda fukuda 249 Dec 6 08:48 manage.py drwxrwxr-x 3 fukuda fukuda 4096 Dec 6 09:31 mysite drwxrwxr-x 3 fukuda fukuda 4096 Dec 6 08:48 templates drwxrwxr-x 6 fukuda fukuda 4096 Dec 6 08:49 tts (pve35) fukuda@xenial:~/pve35$ ls wrm_tts/mysite -l total 20 -rw-rw-r-- 1 fukuda fukuda 0 Dec 6 08:48 __init__.py -rw-rw-r-- 1 fukuda fukuda 3024 Dec 6 09:31 mod_settings.py drwxrwxr-x 2 fukuda fukuda 4096 Dec 6 08:50 __pycache__ -rw-rw-r-- 1 fukuda fukuda 3349 Dec 6 08:48 settings.py -rw-rw-r-- 1 fukuda fukuda 457 Dec 6 08:48 urls.py -rw-rw-r-- 1 fukuda fukuda 393 Dec 6 08:48 wsgi.pyここで、wsgi.py を若干変更して
import os from django.core.wsgi import get_wsgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.mod_settings") application = get_wsgi_application()のようにし、これによって
- mod_wsgi を介さない場合(つまり runserver
を使う場合)は、
mysite/settings.py
(DEBUG=True) - mod_wsgi を介する場合は、
mysite/mod_settings.py
(DEBUG=False, ALLOWED_HOSTS=['.otacky.jp'])
これを、Django の dev-server (runserver) で公開する……
(pve35) fukuda@xenial:~/pve35/wrm_tts$ python manage.py migrate (pve35) fukuda@xenial:~/pve35/wrm_tts$ python manage.py runserver 0.0.0.0:8000 Performing system checks... System check identified no issues (0 silenced). December 08, 2015 - 15:10:33 Django version 1.8.7, using settings 'mysite.settings' Starting development server at http://0.0.0.0:8000/ Quit the server with CONTROL-C. ....Firefox から http://xenia:8000/ でアクセスして OK を確認。(まだ、 Virtual Host を使ってないので、URL の詳細は関係しない。)
次に(mod_wsgi に含まれている)runmodwsgi を使って httpd.conf を作り、Apache で公開する……
#1 (pve35) fukuda@xenial:~/pve35$ sudo chown :www-data wrm_tts #2 (pve35) fukuda@xenial:~/pve35/wrm_tts$ python manage.py collectstatic #3 (pve35) fukuda@xenial:~/pve35/wrm_tts$ sudo ../bin/python ./manage.py \ runmodwsgi --setup-only --port=80 --user www-data --group www-data \ --server-root=/etc/mod_wsgi-express-80 Successfully ran command. Server URL : http://localhost/ Server Root : /etc/mod_wsgi-express-80 Server Conf : /etc/mod_wsgi-express-80/httpd.conf Error Log File : /etc/mod_wsgi-express-80/error_log (warn) Environ Variables : /etc/mod_wsgi-express-80/envvars Control Script : /etc/mod_wsgi-express-80/apachectl ..... #4 fukuda@xenial:~/pve35$ sudo /etc/mod_wsgi-express-80/apachectl startここに、
- #1) db.sqlite3 とその直上のディレクトリは、apache からの write permission が要るので、group を www-data としている。(必須!)
- #2) mod_wsgi + Apache では (runserver と違って) static/media
ファイルの位置を良きにはからってくれないので、
特別な場所 (
wrm_tts/htdocs/
) に集めておく。 - #3) sudo は pyvenv の PATH を引き継がないので、使う python を明示的に指示してやる必要がある。
- #4) これで、apache daemon が起動される。 スタートアップ時に自動で起動するには、別途工夫が要る。
http://xenial
にアクセスして、応答を確認できた。
(ちなみに、上の #1, #2 はこの後の Virtual Host
の実現に必須。)
Debian Virtual Host で公開
以上までで、Apache + mod_wsgi-express で Django Project を公開できた訣だが、 前述のように、これを Virtual Host にする方法がよく解らなかった。
一方で、古い mod_wsgi (-3.4) では既に Virtual Host
の一つにできている。
なので、今回も……という事で、その古い wrm_tts.conf
を使って、その HostName, WSGIScriptAlias ディレクティブだけ変更して
fukuda@xenial:~/pve35$ sudo a2enmod wsgi Module wsgi already enabled fukuda@xenial:~/pve35$ sudo a2ensite wrm_tts.conf Site wrm_tts already enabled fukuda@xenial:~/pve35$ sudo systemctl start apache2とやってみたが、Firefox からアクセスを試みた結果は Internal Server Error ……。 error.log には、 "ImportError: cannot import name 'multiarray'" などと有って、前途多難を感じさせる。
それでは、という事で、
(PyVenv の) pip でインストールした最新版 mod_wsgi-4.4.21 を、deb-package
のように一気にインストールする方法を捜したが、なかなか見付からない。
(少なくとも、mod_wsgi モジュールには含まれてないのは確か。)
なので、libapache2-mod-wsgi-py3 の mod_wsgi.so
の実体だけを置き換える事を試みた。つまり……
fukuda@xenial:~/pve35$ dpkg-query -L libapache2-mod-wsgi-py3 ..... /usr/lib/apache2 /usr/lib/apache2/modules /usr/lib/apache2/modules/mod_wsgi.so-3.4 /usr/lib/apache2/modules/mod_wsgi.so-3.5 /etc /etc/apache2 /etc/apache2/mods-available /etc/apache2/mods-available/wsgi.conf /etc/apache2/mods-available/wsgi.load /usr/lib/apache2/modules/mod_wsgi.so fukuda@xenial:~/pve35$ ls -l /usr/lib/apache2/modules/mod_wsgi* lrwxrwxrwx 1 root root 15 Dec 8 17:05 /usr/lib/apache2/modules/mod_wsgi.so -> mod_wsgi.so-3.4 -rw-r--r-- 1 root root 207952 Nov 30 02:10 /usr/lib/apache2/modules/mod_wsgi.so-3.4 -rw-r--r-- 1 root root 207952 Nov 30 02:10 /usr/lib/apache2/modules/mod_wsgi.so-3.5となっているので、
fukuda@xenial:/usr/lib/apache2/modules$ sudo unlink mod_wsgi.so fukuda@xenial:/usr/lib/apache2/modules$ sudo ln -s \ /home/fukuda/pve35/lib/python3.5/site-packages/mod_wsgi/server/mod_wsgi-py35.cpython-35m-x86_64-linux-gnu.so \ mod_wsgi.so fukuda@xenial:/usr/lib/apache2/modules$ sudo systemctl restart apache2とやったところ、No Error で上手く動いてくれた。
そこで、改めて /etc/apache2/sites-available/wrm_tts.conf
を編集して、(WSGI の) daemon mode に特化した設定にする……
#1 # WSGIPythonPath /home/fukuda/pve35/lib/python3.5/site-packages:/home/fukuda/pve35/ne_tts <VirtualHost *:80> ServerName xenial2.otacky.jp #2 WSGIScriptAlias / /home/fukuda/pve35/wrm_tts/mysite/wsgi.py WSGIApplicationGroup %{GLOBAL} #3 WSGIDaemonProcess xenial2.otacky.jp python-path=/home/fukuda/pve35/wrm_tts:/home/fukuda/pve35/lib/python3.5/site-packages WSGIProcessGroup xenial2.otacky.jp #4 Alias /static/ /home/fukuda/pve35/wrm_tts/htdocs/ Alias /favicon.ico /home/fukuda/pve35/wrm_tts/htdocs/tts/img/favicon.ico <Directory /home/fukuda/pve35/wrm_tts/htdocs> Require all granted </Directory> <Directory /home/fukuda/pve35/wrm_tts/mysite > <Files wsgi.py> Require all granted </Files> </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>ここに、
- #1) daemon mode では、WSGIPythonPath を使えない。
- #2) 最重要の directive. どの Django Project を呼ぶかは、ここで決まる。
- #3) WSGIPythonPath の代りに、この python-path オプションで、呼ぶべき Python とそのモジュールを指定する。
- #4) Django Project の static/media file を集めたディレクトリを指定
ともあれ、mod_wsgi + Apache で Django Project が公開できて、下のような動作をしている事が確認できた。
Keep Alive の時間が短かすぎて、この図では Server Status のプロセス(スレッド?)しか表示されていないが、 ページを要求した直後は、xenial2.otacky.jp:80 へのアクセスも表示される。複数の Django Project を公開
通常の(mod_wsgi を使わない)ページでは、Name-based Virtual Host は実現できていて、実際、otacky.jp, waremo.com 合わせて、 六つ程のページを公開している。それに、さらに、mod_wsgi 経由の Django Project を一つ加える事もできている(未公開だが)。ここでさらに複数の Django Project を加えたい、 という今回のお題にとっては、WSGIPythonPath を、 <VirtualHost :80></VirtualHost> の中に置けない、 というのがネックだった訣だが、以上の検討の中で、 これを WSGIDaemonProcess の python-path パラメータの中に置ける事が確認できた。 つまり、それぞれの <VirtualHost>の中で、ServerName, WSGISCriptAlias, WSGIDaemonProcess (の python-path) を対応する Django Project を指すようにしてやれば、 全く独立した host にできる。
実際に、000-otacky.conf (http://xenial.otacky.jp), net_tts.conf (http://xenial1.otacky.jp), wrm_tts.conf (http://xenial2.otacky.jp) を立てて実験してみたが、相互に干渉する事なく、また、 まったく独立に a2ensite/a2dissite で抜き差しできた。 言うまでもないが、後の二つの Django project は独立に db.sqlite3 を保持できる。
まとめ
Ubuntu-16.04 において、- 最新の mod_wsgi を Debian Virtual Host に嵌め込む——つまり、
libapache2-mod-wsgi-py3 を apt-get install して、その中の
/usr/lib/apache2/module/mod_wsgi.so
が、PyVenv の mod_wsgi-py35.... を指すように変更。 - mod_wsgi を Daemon mode で動かす——つまり、
/etc/apache2/hosts-available/xxxx.conf
の中で、WSGIPythonPath ではなく、WSGIDaemonProcess で、pyvenv の Python と、Django Project を指定する。
2015-11-12 (Thu): BLAS/LAPACK と NumPy (その 2)
「今や BLAS は(サブルーチン集ではなく) API」を知らなかったというのもちょっと恥ずかしいが、 その性能改善の度合いが、 (「並列化」ではなく)いかに主メモリへのアクセスを減らすかで決まる、 を知らなかったのもかなり……ともあれ、Ubuntu on (VMware) 上の比較で、Mac-mini の Core i5 が(core 数が半分でも)Core i7 と遜色ない性能を出している事から、Fusion を介さず 直接 OS X の上で走る NumPy の処理能力に期待が高まる……
OS X での Numpy (vecLib 版)
この頃は、Python で何かを試したいという時、 pyvenv (Python の Virtual Environment) の中でやる事が増えたので、NumPy についても、 pip (pip-tools) でインストールしたものを使う事が多い。 MacPorts 版より更に安定性が向上し、 かつアップグレード(本家への追随)が迅速なような気がする。 (先の '@' の「味見」には Python-3.5 と numpy-1.10 が必要だったので、 これ(pyvenv 環境下)で試したのだった。)
(pve35) fukuda@falcon:~/pve35% pip freeze
ipython==4.0.0
ipython-genutils==0.1.0
....
numpy==1.10.1
....
(pve35) fukuda@falcon:~/pve35% ipython
Python 3.5.0 (default, Sep 15 2015, 23:58:24)
Type "copyright", "credits" or "license" for more information.
IPython 4.0.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: import numpy as np
In [2]: np.__version__
Out[2]: '1.10.1'
In [3]: np.show_config()
....
blas_opt_info:
define_macros = [('NO_ATLAS_INFO', 3), ('HAVE_CBLAS', None)]
extra_compile_args = ['-msse3', '-I/System/Library/Frameworks/vecLib.framework/Headers']
extra_link_args = ['-Wl,-framework', '-Wl,Accelerate']
atlas_3_10_blas_threads_info:
NOT AVAILABLE
lapack_opt_info:
define_macros = [('NO_ATLAS_INFO', 3), ('HAVE_CBLAS', None)]
extra_compile_args = ['-msse3']
extra_link_args = ['-Wl,-framework', '-Wl,Accelerate']
....
In [4]: A = np.random.rand(1000, 1000)
In [5]: %timeit B = np.linalg.inv(A)
10 loops, best of 3: 70.5 ms per loop
In [7]: C = np.random.rand(1024, 1024)
In [8]: %timeit D = np.fft.fft2(C)
10 loops, best of 3: 70.6 ms per loop
show_config()
の出力にあるように、
BLAS/LAPACK は vecLib
を使っていて、linalg.inv() に 70.5 ms かかっており、
Vivid の OpenBLAS (82.6 ms) に比べて、僅かに速い。
(fft.fft2() については 70.6 ms 対 53.3 ms
でかなり負けているが。)
OS X での Numpy (MacPorts の OpenBLAS)
Core 数が半分の vivid に対して、あまり改善されていない(fft.fft2 についてははっきり劣化している)事が癪で、 むりやり OpenBLAS を作ってみる事にした。(fft は BLAS に依存していないので改善される見込みはないだろう、 という理性の声は圧殺して……)pip にはインストール時のパラメータを追加する事はできなさそうなので、 MacPorts 版で openblas を付け加える事を試みた。
fukuda@falcon:~% sudo port install py35-numpy +openblas +scalapack
fukuda@falcon:~% sudo port installed py35-numpy
The following ports are currently installed:
py35-numpy @1.10.1_1+gfortran+openblas (active) #1)
fukuda@falcon:~% ipython-3.5
Python 3.5.0 (default, Sep 15 2015, 23:58:24)
....
In [1]: import numpy as np
In [2]: np.__version__
Out[2]: '1.10.1'
In [3]: np.show_config()
....
lapack_opt_info:
define_macros = [('NO_ATLAS_INFO', 3), ('HAVE_CBLAS', None)]
extra_compile_args = ['-msse3']
extra_link_args = ['-Wl,-framework', '-Wl,Accelerate']
....
openblas_info: #2)
language = c
define_macros = [('HAVE_CBLAS', None)]
libraries = ['openblas']
library_dirs = ['/opt/local/lib']
blas_opt_info:
language = c
define_macros = [('HAVE_CBLAS', None)]
libraries = ['openblas']
library_dirs = ['/opt/local/lib']
In [4]: A = np.random.rand(1000, 1000)
In [5]: %timeit B = np.linalg.inv(A)
10 loops, best of 3: 70.9 ms per loop
In [6]: C = np.random.rand(1024, 1024)
In [7]: %timeit D = np.fft.fft2(C)
10 loops, best of 3: 71.3 ms per loop
ここに、
- #1) '+openblass +scalapack' としても、variant としては、openblas しか入らないし
- #2) 実際にリンクされるのも BLAS として openblas のみ。 (LAPACK はディフォルトのまま。)
OpenBLAS と Numpy のビルド
そろそろ諦めムードが漂い始めるが、まあ、ここまで来たので、 BLAS/LAPACK をともども(Ubuntu のように)OpenBLAS からのライブラリで揃えてみよう、と決心した。そのためには、OpenBLAS を(LAPACK 込みで)ビルドし、 そのライブラリを指して、NumPy をビルドすれば良いようだ。
まず OpenBLAS から。
http://www.openblas.net/ から OpenBLAS-0.2.15.tar.gz をダウンロード。
fukuda@falcon:~/build% tar xzvf Downloads/OpenBLAS-0.2.15.tar.gz fukuda@falcon:~/build% cd OpenBLAS-0.2.15 fukuda@falcon:~/build/OpenBLAS-0.2.15% make NO_LAPACK=0 NO_LAPCKE=0 fukuda@falcon:~/build/OpenBLAS-0.2.15% sudo make install fukuda@falcon:~/build/OpenBLAS-0.2.15% ls /opt/OpenBLAS/lib -l total 49232 drwxr-xr-x 3 root wheel 102 Nov 10 11:19 cmake/ lrwxr-xr-x 1 root wheel 30 Nov 10 18:18 libopenblas.a -> libopenblas_haswellp-r0.2.15.a lrwxr-xr-x 1 root wheel 34 Nov 10 18:18 libopenblas.dylib -> libopenblas_haswellp-r0.2.15.dylib* -rw-r-*-r-*- 1 root wheel 27388432 Nov 10 18:17 libopenblas_haswellp-r0.2.15.a -rwxr-xr-x 1 root wheel 23014448 Nov 10 18:18 libopenblas_haswellp-r0.2.15.dylib*Install guide には事もなげに、「単に make すればよい」なんて書いてあるけど、で、多分 Linux ではそれでよいのだろうけど、OS X ではそんなにすんなり行かなかった。
- まず、cmake ではうまくコンパイルできない。cmake の後の make の途中の link で躓く。ただ、make から始めても、TARGET 他はちゃんと自動検出するようだ。
- しかし、LAPACK も runtime library に含めるには make の際に、NO_LAPACK と NO_LAPCKE を nil にしてやる必要がある。
- 延々とやった compile/link の成果は、
/opt/OpenBLAS/lib/
の下にlibopenblas_haswellp-r...
としてインストールされる。
次に、NumPy そのもののビルド。Git で clone したソースの中にある
cite.cfg.example
を編集して対のようなエントリを作る([openblas] のエントリの
uncomment だけで OK?)
# cite.cfg [ALL] #library_dirs = /usr/local/lib #include_dirs = /usr/local/include library_dirs = /opt/OpenBLAS/lib include_dirs = /opt/OpenBLAS/include [openblas] libraries = openblas library_dirs = /opt/OpenBLAS/lib include_dirs = /opt/OpenBLAS/include runtime_library_dirs = /opt/OpenBLAS/libその後、setup.py でビルドする。
(pve35) fukuda@falcon:~/pve35/Git% git clone http://github.com/numpy/numpy (pve35) fukuda@falcon:~/pve35/Git/numpy% python setup.py build_ext --inplace -j 4この、
setup.py build_ext --inplace
が重要で、こうしておいて、ここから ipython を立ち上げると、
今ビルドした NumPy が import される。
(pve35) fukuda@falcon:~/pve35/Git/numpy% ipython
Python 3.5.0 (default, Sep 15 2015, 23:58:24)
....
In [1]: import numpy as np
In [2]: np.__version__
Out[2]: '1.11.0.dev0+cdef8d3'
In [3]: np.show_config()
openblas_info:
runtime_library_dirs = ['/opt/OpenBLAS/lib']
define_macros = [('HAVE_CBLAS', None)]
library_dirs = ['/opt/OpenBLAS/lib']
libraries = ['openblas', 'openblas']
language = c
openblas_lapack_info:
runtime_library_dirs = ['/opt/OpenBLAS/lib']
define_macros = [('HAVE_CBLAS', None)]
library_dirs = ['/opt/OpenBLAS/lib']
libraries = ['openblas', 'openblas']
language = c
lapack_opt_info:
runtime_library_dirs = ['/opt/OpenBLAS/lib']
define_macros = [('HAVE_CBLAS', None)]
library_dirs = ['/opt/OpenBLAS/lib']
libraries = ['openblas', 'openblas']
language = c
blas_opt_info:
runtime_library_dirs = ['/opt/OpenBLAS/lib']
define_macros = [('HAVE_CBLAS', None)]
library_dirs = ['/opt/OpenBLAS/lib']
libraries = ['openblas', 'openblas']
language = c
In [4]: A = np.random.rand(1000, 1000)
In [6]: %timeit B = np.linalg.inv(A)
10 loops, best of 3: 71.2 ms per loop
In [8]: C = np.random.rand(1024, 1024)
In [9]: %timeit D = np.fft.fft2(C)
10 loops, best of 3: 72 ms per loop
np.__version__
と np.show_config()
から、確かに新しくビルドした NumPy が import されており、
しかもその NumPy は BLAS も LAPACK
も先程の OpneBLAS でビルドした library をリンクしている、
取り敢えず目出度い……
が、パフォーマンスは殆んど変化がない(全く改善されていない。)
とすると、 Mac-mini (2-core/4-thread) の Yosemite と、 それから 2-vCore のみアサインした Fusion 上の Ubuntu の間でそれ程パフォーマンスが変わらないのは何故か、という疑問が残るが、 これは多分、Hyper Threading でパフォーマンスが 2 倍になる訣ではなく、高々 1.2 ~ 1.3 倍に過ぎない事を反映しているのだと思う。
まとめ
先の Ubuntu での結果も含めて、大まかに次の事が言えるのではないか……- Numpy の行列計算のルーチンには様々な実装があるが、OS X では、vecLib がディフォルト。Ubuntu ではいくつか選択肢が有るが、 OpenBLAS が最もパフォーマンスが高い。
- vecLib と OpenBLAS のパフォーマンスは同程度。
- なので、OS X では、MacPorts の NumPy を使い、 Ubuntu では deb-pkg の NumPy と libopenblas-dev を使う、が正解。
- BLAS/LAPACK のような "Number Cruncher" メインの応用では、Hyper Threading は効果がない。
2015-11-11 (Wed): BLAS/LAPACK と NumPy (その 1)
ここしばらくは NumPy を使う機会は極稀にしかなく、それも matplotlib に食わせるデータを作る等が主だった。 つまり、本来の(?)行列演算をガシガシなんて事は殆んど無かった訣だが、 行列乗算の二項演算子 ('@') が新たに導入された事をきっかけに、 そのあたり(行列演算)もちょっと弄ってみた。で、その変わり様に驚いた。ただ、「変った」と言っても、その比較の対象というか「変わる前」がとても曖昧で、 Numarray, Numeric などが、NumPy の統合されたあたりの記憶が、 FORTRAN で「QR 分解」のルーチンを書いていた頃の話とごっちゃになっている (要は、15 年くらいの幅があるかも……ってくらいいい加減。) 当然「どう変わったか」についてはよく解らないので、 今はどうなっている(と思っている)かを纏めてお茶を濁す。
ちなみに、使った環境は
- falcon: OS X Yosemite (10.10.5), on Mac-mini (late 2014)
- CPU: Core i5, 2.6GHz 2 cores, 4 threads,
- Memory: 16GB, 1600GHz, DDR3
- Storage: Fusion Drive (2TB)
- vivid: Ubuntu-15.04, on VMware Fusion (7.1.2) on falcon.
Fusion にアサインした H/W:
- CPU: 2 processor cores
- Memory: 4GB
- Storage: 20GB
そもそも BLAS/LAPACK って何?
言うまでもなく、BLAS/LAPACK (かつては LINPACK だった?) は、行列計算を「高速」に実行するルーチン集 と言いたいところだが(実際 BLAS は、Basic Linear Algebra Subprograms の略)、 今や "Library API" になっている……今さら、と笑うなかれ、 これは私にとっては「大発見」だった。で、その「実装」に Intel KML, ACML, GotoBLAS, OpenBLAS, Accelerate, etc. etc. が有る。(ATLAS や reference BLAS も「実装」の一つ。)
で、長くてややこしい話を煎じ詰めると
- Linux では OpenBLAS, OS X では Accelerate を考えておけば良い。 (他のは性能が落ちるか、さもなければ有償。)
- ATLAS や reference BLAS は(NumPy の中でもよく言及されているが) とりあえず無視する。
- BLAS/LAPACK は基本的に FORTRAN で書かれているので、 C から効率的に呼ぶための C-binding が有る。これにも色々有るが、 OpenBLAS には、CBLAS と LAPACKE が含まれていて、 とりあえずこれに決め打ち、で良さそう。
- Linux (Ubuntu) の OpenBLAS は、libopenblas-* という形で供給される。
fukuda@vivid:~$ apt list --installed libopenblas-* Listing... Done libopenblas-base/vivid,now 0.2.12-1ubuntu1 amd64 [installed] libopenblas-dev/vivid,now 0.2.12-1ubuntu1 amd64 [installed] fukuda@vivid:~$ ls /usr/lib/libopen* /usr/lib/libopenblas.a /usr/lib/libopenblas.so /usr/lib/libopenobex.so.1.5.0 /usr/lib/libopenblasp-r0.2.12.a /usr/lib/libopenblas.so.0 /usr/lib/libopenblasp-r0.2.12.so /usr/lib/libopenobex.so.1
- OSX では Accelerate であるが、その実体は vecLib フレームワークの下の
libBLAS.dylib:
fukuda@falcon:~% ls -l /System/Library/Frameworks/Accelerate.framework/Versions/A/\ Frameworks/vecLib.framework/Versions/A/ total 9004 drwxr-xr-x 14 root wheel 476 Oct 22 12:31 Headers/ drwxr-xr-x 5 root wheel 170 Aug 21 08:58 Resources/ drwxr-xr-x 3 root wheel 102 Aug 21 08:58 _CodeSignature/ -rwxr-xr-x 1 root wheel 3483824 Sep 10 2014 libBLAS.dylib* -rwxr-xr-x 1 root wheel 9101808 Sep 10 2014 libLAPACK.dylib* -rwxr-xr-x 1 root wheel 254432 Sep 10 2014 libLinearAlgebra.dylib* -rwxr-xr-x 1 root wheel 3519360 Nov 18 2014 libvDSP.dylib* -rwxr-xr-x 1 root wheel 2631056 Nov 18 2014 libvMisc.dylib* -rwxr-xr-x 1 root wheel 38192 Nov 18 2014 vecLib*
(しかし、これを見ていると、'Accelerate' を「BLAS の実装の一つ」と言って良いのかな、という気もしてくる :-)) - OpenBLAS も Accerelate (の libBLAS) も、multithread 対応になっている。 (今度は、この最大スレッド数の「設定の仕方」が新たな悩み。) ちなみに、'shared-memory parallelism' はとりも直さず 'multithreading' の事(らしい。)
一方の LAPACK も 'Library API' と考えれば、かなりすっきりする。つまり「BLAS に基づいた 線形代数演算のルーチン(の規格)で、色々な実装がある」という塩梅……だが、 どうもこの認識は古くなってしまったようだ。 netlib.org のサイトには、LAPACK vendor library や Linux Distribution のリストがあるが、そのうちの多くがリンク切れか、 全く無関係なページに飛ばされる。なので、有り体に言うと:
- Debian (Ubuntu) では、(サイトで示唆されている)liblapack
のパッケージは無くなり、libopenblas
のパッケージに含まれている(liblapack.so が無くなった訣ではない)
fukuda@vivid:~$ ls /usr/lib/liblapack* /usr/lib/liblapack.a /usr/lib/liblapack_atlas.so.3 /usr/lib/liblapack.so.3 /usr/lib/liblapack_atlas.a /usr/lib/liblapack_atlas.so.3gf /usr/lib/liblapack.so.3gf /usr/lib/liblapack_atlas.so /usr/lib/liblapack.so
- OSX でも、'Velocity Engine' というパッケージは無くなり(El Capitan
のページに飛ばされる :-)、
vecLib framework に含まれるようになっている。(上記の ls 出力の中の
libLAPACK.dylib*
がそれ。)
lapack/
と lapack-netlib/
というディレクトリがあり、それぞれ、C と FORTRAN のソースが入っている
(後者は、LAPACK-3.5.0 最新版)。試しにコンパイルしてみると
fukuda@falcon:~/build/OpenBLAS-0.2.15% make TARGET=HASWEL
.....
OpenBLAS build complete. (BLAS CBLAS LAPACK LAPACKE)
OS ... Darwin
Architecture ... x86_64
BINARY ... 64bit
C compiler ... CLANG (command line : clang)
Fortran compiler ... GFORTRAN (command line : gfortran)
Library Name ... libopenblas_haswellp-r0.2.15.a
(Multi threaded; Max num-threads is 4)
のような結果となった。(LAPACKE は LAPACK の C-binding.)
つまり、OpenBLAS を build すれば、BLAS と LAPACK
の両方を含んだ
dynamic link library ができあがるという事らしい。
Ubuntu-15.04 での NumPy
Debian (Ubuntu) では、先の BLAS/LAPACK の実装がパッケージとして用意されており、 しかも、インストールの後その中から実際にリンクする組合せを選べるようになっている。 つまり、NumPy は/usr/lib/{libblas.so.3|liblapack.so.3}
をリンクして import されるが、そのリンク先を次のようにして変更する……
fukuda@vivid:~$ sudo update-alternatives --config libblas.so.3 There are 3 choices for the alternative libblas.so.3 (providing /usr/lib/libblas.so.3). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/lib/openblas-base/libblas.so.3 40 auto mode 1 /usr/lib/atlas-base/atlas/libblas.so.3 35 manual mode 2 /usr/lib/libblas/libblas.so.3 10 manual mode 3 /usr/lib/openblas-base/libblas.so.3 40 manual mode fukuda@vivid:~$ sudo update-alternatives --config liblapack.so.3 There are 3 choices for the alternative liblapack.so.3 (providing /usr/lib/liblapack.so.3). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/lib/openblas-base/liblapack.so.3 40 auto mode 1 /usr/lib/atlas-base/atlas/liblapack.so.3 35 manual mode 2 /usr/lib/lapack/liblapack.so.3 10 manual mode 3 /usr/lib/openblas-base/liblapack.so.3 40 manual mode(勿論、libopenblas-dev や、libatlas-base-dev は予め apt-get install しておく必要がある。)
この条件(以下、(blas, lapack) = (0, 0) と略記)の下で、簡単にパフォーマンスを確認してみた。
fukuda@vivid:~$ ipython3
Python 3.4.3 (default, Mar 26 2015, 22:03:40)
Type "copyright", "credits" or "license" for more information.
IPython 2.3.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: import numpy as np
In [2]: np.__version__
Out[2]: '1.8.2' #1)
In [3]: np.show_config() #2)
....
lapack_opt_info:
define_macros = [('NO_ATLAS_INFO', 1)]
language = f77
library_dirs = ['/usr/lib']
libraries = ['lapack', 'blas']
....
blas_info:
language = f77
library_dirs = ['/usr/lib']
libraries = ['blas']
blas_opt_info:
define_macros = [('NO_ATLAS_INFO', 1)]
language = f77
library_dirs = ['/usr/lib']
libraries = ['blas']
....
lapack_info:
language = f77
library_dirs = ['/usr/lib']
libraries = ['lapack']
....
In [4]: A = np.random.rand(1000, 1000)
In [5]: %timeit B = np.linalg.inv(A) #3)
10 loops, best of 3: 82.6 ms per loop
In [6]: C = np.random.rand(1024, 1024)
In [7]: %timeit D = np.fft.fft2(C) #4)
10 loops, best of 3: 53.5 ms per loop
- #1) Vivid で得られる最新版を使ったが Python-3/ipython ともども、ちょっと古い。
- #2) numpy モジュールはこのようなメソッドを持っていて、
ビルド時のパラメータを表示する。この場合、上述のように、
/usr/lib/
以下にある symbolic link を指している。 - #3) numpy.linalg.inv は逆行列の計算。%timeit は iPython のディレクティブで、CPU 時間を正確に測定する。
- #4) リファレンスのため、fft.fft2 (2 次元 FFT) の計算時間を測定。
Config | linalg.inv() (ms) |
fft.fft2() (ms) | Notes *1) |
---|---|---|---|
(0, 0) | 82.6 | 53.3 | OpenBLAS |
(1, 1) | 269 | 54.1 | ATLAS |
(2, 2) | 1030 | 53.5 | reference BLAS(?) |
FFT の計算時間に殆んど変化が無いのに対し、 逆行列の方は、きれいに、OpenBLAS > ATLAS > reference BLAS の順になっている。(ATLAS との差がこれ程大きいのはちょっと意外。)
絶対値がどれ程のものか見当をつけるために kashi さん のところでの結果と比べられるよう、追加の測定をしてみた。
In [2]: A = np.random.rand(5000, 5000) In [3]: %timeit B = np.linalg.inv(A) 1 loops, best of 3: 6.87 s per loop In [4]: import time In [5]: t=time.time(); B = np.linalg.inv(A); time.time() - t Out[5]: 7.0319378376007085000 x 5000 の行列についての計算時間は、7.0 秒と出たが、 Kashi さんの結果は、6.0 秒との事。H/W と OS は、それぞれ
Kashi さん: OS: Ubuntu-14.04 (on VMware) CPU: i7 3770T, 4 cores, 4 GB, 今回: OS: Ubuntu-15.04 (on VMware Fusion) CPU: i5 4278U, 2 cores (threads?), 4GB, 2.6 GHzなので、妥当な性能が出ている、と言ってよいだろう。 (Core 数とクロック周波数からすると、今回の結果は出来過ぎ?)
2015-11-04 (Wed): やっぱり Time Machine の実現は難しかった
いや、実は OSX の TM の話。(Netatalk といい、Time Machine といい、ネタにするには格好の……)Netatalk を 3.1.7 にして、ようやく動き始めた、と思っていたが、 また偶に Time Machine がバックアップに失敗するようになった。 大概は「バックアップが完了しませんでした」だが、 一度など、「コネクションが張れません」とやられた (ssh などはちゃんと動いているので、そんな筈はないのだが……)
もう一遍だけ、first backup からやり直す事にした。 今度は、もし実験に成功したらそのまま実稼働に移行できるように、fstab を設定する。(ついでに、Time Machine が乗っている Hawk の default user の fukuda に固有のバックアップにする事も試みる。)
pi@raspi06:~$ sudo umount /home/share pi@raspi06:~$ sudo systemctl stop netatalk pi@raspi06:~$ sudo adduser fukuda pi@raspi06:~$ sudo addgroup fukuda sudo pi@raspi06:~$ su fukuda fukuda@raspi06:~$ mkdir tm_hawk #1) fukuda@raspi06:~$ sudo chmod 777 tm_hawk fukuda@raspi06:~$ exit pi@raspi06:~$ sudo blkid ..... /dev/sda1: LABEL="EFI" UUID="67E3-17ED" TYPE="vfat" \ PARTLABEL="EFI System Partition" PARTUUID="1ba9a00f-4f1a-495c-9fd3-9366ab1e5357" .... /dev/sda5: UUID="434f1e3f-f871-42a7-8352-7be11f6b9bef" TYPE="ext4" \ PARTLABEL="Untitled 4" PARTUUID="189c0679-699b-4a4c-9a1b-5cc8009596f8" pi@raspi06:~$ sudo emacs /etc/fstab pi@raspi06:~$ cat /etc/fstab proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat defaults 0 2 /dev/mmcblk0p2 / ext4 defaults,noatime 0 1 ..... #2) UUID="434f1e3f-f871-42a7-8352-7be11f6b9bef" /home/fukuda/tm_hawk ext4 defaults 0 2ここで、
- #1) 最初これをやるのをさぼったら、Time Machine
からアクセスできなかった。早くも目論見は外れた訣だが、
その下にできるバックアップファイルは
fukuda@raspi06:~$ ls -l tm_hawk total 24 drwx------ 2 root root 16384 Oct 30 17:58 lost+found drwx--S--- 3 fukuda fukuda 4096 Nov 5 04:45 Taka Fukuda’s MacBook Air.sparsebundle
のようになるので、一応のセキュリティは実現できたように思う。 - #2) ここで最後のところを '0 2' にするのは大事。うっかり '0 0' などとやると、Raspi が正常に立ち上がらなくなる……
/usr/local/etc/afp.conf
に、以下のエントリを追加
[Hawks Time Machine] path = /home/fukuda/tm_hawk time machine = yes vol size limit = 512000以下
% pi@raspi06:~$ sudo mount -a % pi@raspi06:~$ sudo systemctl restart netatalkとして、Hawk から、Time Machine backup を試み、 正常にスタートする事を確認してから、
% pi@raspi06:~$ sudo reboot
とし、Raspi が立ち上がるのを確認して、Hawk の Time Machine
から first full-backup を開始。
Full-backup にはやはり 10 時間かかった。その後、Raspi のリブート、 Time Machine の ON/OFF、手動の backup 開始、などの意地悪テストを丸一日続けているが、不具合は出ていない。
まとめ(の代りの)メモ:
- Raspberry Pi 2 と Netatalk (-3.1.7) で、実用的な Time Machine 用
の NAS が実現できた。
- Netatalk-2.2.2/5 は、Time Machine に対応しきれていない。
- USB-HDD は、ext4 でフォーマットする必要あり
- つまり、USB-HDD 直結で作ったバックアップファイルを、 NAS に継ぎ変えて……なんて事はできない。(純正 Time Capsule はどうなんだろう。)
- WLAN 越し(Hawk と AP の間が WLAN) だと、
実効スループットは 2 - 3 MB/s (11n による制限されている。)
- Ethernet に切り換えても、速くならない(むしろ遅くなる)。 こちらは Time Machine からの制限だろう。
- いずれにせよ、Raspi 2 の処理能力の範囲内(top によると CPU の占拠率は、高々 13% くらい。)
2015-11-01 (Sun): Raspberry Pi で Netatalk-3
Raspi (Raspbian Jessie on Raspberry 2 B) 上の netatalk、「意外にすんなり動いたぜ」と思ったが、 Time Machine による最初の full-backup の後、(最初、もしくは二度目の) 「定時(部分)バックアップ」でいきなり躓いた……転送が終った後の cleaning up が終らない。10 時間あまりも時間をかけて full-backup を取った後の、何とも微妙な転け方で、 どうしたものかと悩んだが、 事が backup 関連だけに、 ここでいい加減に済ませては先々後悔しそうな気がして、 この際とことん付き合ったろやないか、と。何故か Debian (従って、Ubuntu や Raspbian) のパッケージは、2.2.2 か 2.2.5 どまり (一昨日使ったのは、 この 2.2.5) だが、実は netatalk は -3.1.7 になっている。 これを build してみる事にした。(コマンドの build なんて何年ぶりやろか。)
既に Ubuntu-15.04 のためのインストールマニュアルは有る。これが既に「大変そう」だが、Raspbian も Debian 由来なので、なんとかなるのではないか。
まず、今走っている netatalk-2.2.5 を止め、package を消去。 netatalk-3.1.7 のビルドに必要なヘッダ群をインストールする。
pi@raspi06:~$ sudo systemctl stop netatalk pi@raspi06:~$ sudo systemctl disable netatalk pi@raspi06:~$ sudo apt-get remove netatalk pi@raspi06:~$ sudo apt-get install build-essential pi@raspi06:~$ sudo apt-get install libevent-dev libssl-dev libgcrypt11-dev \ libkrb5-dev libpam0g-dev libwrap0-dev libdb-dev libtdb-dev libmysqlclient-dev pi@raspi06:~$ sudo apt-get install libavahi-client-dev libacl1-dev \ libldap2-dev libcrack2-dev systemtap-sdt-dev libdbus-1-dev pi@raspi06:~$ sudo apt-get install libdbus-glib-1-dev libglib2.0-dev \ tracker libtracker-sparql-1.0-dev libtracker-miner-1.0-devついで、netatalk-3.1.7 のソースをダウンロードして、ビルド・インストール:
pi@raspi06:~$ wget http://sourceforge.net/projects/netatalk/files/netatalk/3.1.7/netatalk-3.1.7.tar.gz pi@raspi06:~$ tar xzvf netatalk-3.1.7.tar.gz pi@raspi06:~$ cd netatalk-3.1.7/ pi@raspi06:~/netatalk-3.1.7$ ./configure \ --with-init-style=debian-systemd --without-libevent --without-tdb \ --with-cracklib --enable-krbV-uam --with-pam-confdir=/etc/pam.d \ --with-dbus-sysconf-dir=/etc/dbus-1/system.d \ --with-tracker-pkgconfig-version=1.0 pi@raspi06:~/netatalk-3.1.7$ make pi@raspi06:~/netatalk-3.1.7$ sudo make installここで最初の config parameter を debian-sysv から debian-systemd に変更した。また、tracker-pkgconfig-version は各自確認するように、とあったが、まだ 1.0 のままだった。 先の xxxx-dev のインストールや、configure の option に間違いなければ、無事コンパイル・インストールは終る筈。 しかし、「10時間かけて full-backup を終えた後に不具合が見つかる」なんて悲劇を避けるために、 きちんと確認した方が良い。
pi@raspi06:~/netatalk-3.1.7$ afpd -V
afpd 3.1.7 - Apple Filing Protocol (AFP) daemon of Netatalk
.....
afpd has been compiled with support for these features:
AFP versions: 2.2 3.0 3.1 3.2 3.3 3.4
CNID backends: dbd last tdb mysql
Zeroconf support: Avahi
TCP wrappers support: Yes
Quota support: Yes
Admin group support: Yes
Valid shell checks: Yes
cracklib support: Yes
EA support: ad | sys
ACL support: Yes
LDAP support: Yes
D-Bus support: Yes
Spotlight support: Yes
DTrace probes: Yes
afp.conf: /usr/local/etc/afp.conf
extmap.conf: /usr/local/etc/extmap.conf
state directory: /usr/local/var/netatalk/
afp_signature.conf: /usr/local/var/netatalk/afp_signature.conf
afp_voluuid.conf: /usr/local/var/netatalk/afp_voluuid.conf
UAM search path: /usr/local/lib/netatalk//
Server messages path: /usr/local/var/netatalk/msg/
各項目がこうなっていなければ、それは多分、
開発用ヘッダのインストールの際に漏れが有ったか、configure
のオプションに誤りが有ったという事。
きちんと、インストールできている事を確認の後、先の例と同様に USB-HDD パーティションをマウントし、それに応じて afp.conf を修正した後、daemon をスタートする
pi@raspi06:~/netatalk-3.1.7$ sudo chmod 777 /home/share pi@raspi06:~/netatalk-3.1.7$ sudo mkfs.ext4 /dev/sda2 pi@raspi06:~/netatalk-3.1.7$ sudo mount /dev/sda2 /home/share pi@raspi06:~/netatalk-3.1.7$ sudo nano /usr/local/etc/afp.conf pi@raspi06:~/netatalk-3.1.7$ cat /usr/local/etc/afp.conf ; Netatalk 3.x configuration file [Global] ; Global server settings [Homes] basedir regex = /home [My Time Machine Volume] path = /home/share time machine = yes vol size limit = 512000 pi@raspi06:~/netatalk-3.1.7$ sudo systemctl restart avahi-daemon pi@raspi06:~/netatalk-3.1.7$ sudo systemctl start netatalkここで触るのが
/etc/netatalk/AppleVolumes.default
ではなく、
/usr/local/etc/afp.conf
である事に注意。
ここまでで、Hawk の [Select Disk ...] に、
My Time Machine Volume on 'raspi06'
が表われるので、それを選択して、バックアップを開始する。
ここでまた一晩待つ。(バックアップ容量 80 GB, WiFi 11n 越しで 12 時間掛った。)
待ち草臥れて、終るのを見逃してしまい、 気がついた時には最初の「部分バックアップ」が終っていた。 その後 10 回程、自動(部分)バックアップをやらせてみた結果が以下。
また、Time Machine に入ってみたりもした。 どうやらうまく動いているようだ。2015-10-31 (Sat): Backup 体制を見直し
先週自宅サーバ (Ubuntu-14.04LTS + ThinkPad X200) の電池を新しくしたので、 来年四月 (Ubuntu-16.04LTS のリリース時期)と言わず、もうちょっと先まで使い続けたい、ついてはその HDD が心配なので、そのバックアップが要るだろう……が事の発端。MacPro (Quadra) が健在だった頃は、2TB の内蔵 HDD を二台積んで、 そのうちの一つを Time Machine の HDD にしていた。 上記自宅サーバ (Lark) や、MacBook (Mavericks, Hawk) は、 自分の作ったファイルだけを rsync で Quadra と同期し、 それを丸ごと、Time Machine に入れていた。 少々オーバーキルの憾みはあるが、ホントに手間いらずだった。
が、その大元になっていた Quadra が逝ってしまい、 その後を継いだ Mac-mini (Falcon) に、HDD 二台持ちのバージョンが無くなっていた、というあたりから、 少々悲しい状態になっていた。つまり 2 TB の USB-HDD に二つの partition を切って、Falcon と Hawk でそれを共有する(普段は Falcon に継いでいて、 たまに、手で Hawk に継ぎ換える……)勿論、Hawk のバックアップは、一月とか 1 Quarter に 1回などというペースになる。
このあたりを何とかもっとスマートにしたい、に加えて、 Lark のフルバックアップを、というのが今回のお題である。
Falcon (Main Desktop) は、専用 USB HDD へ
全ファイルサーバを NAS で統一……と当初は思ったが、 お値段が張るのと、Time Machine との相性が心配。 特に、この部分は全てのバックアップ(冗長性)の大元になるので、 信頼性を第一にしたいという事で、WD の Red (2 TB) を載せた LogiTech の USB-HDD を直結する事にした。 現状と代わり映えしない、という憾みもあるが、 2 TB を専有させる事で、「ケーブルの抜き差し」とか、 「満杯になって古いファイルを消す」際の不安(少し前に、 これで Volume 全体が壊れた)は、 かなり軽減できるのではないか、と思う。もうひとつの重大な要素は「ファイルフォーマット」 これまでは、as is の NTFS をそのまま使っていたが、 今回、OSX につないでから、 HFS+ (Journaled, case-insensitive) で再フォーマットした。どうやらこれは大正解だったみたいで、 前の HDD で最初のバックアップを取った時、10 時間以上かかったものが、今回(ディスクの容量は増えているのに)5 時間で済んだ。
その他のホスト (OSX + Ubuntu) はファイルサーバで
これらのバックアップがいい加減で良い、という訣ではないのだが、- 稼働中の自宅サーバ (Lark) に USB ケーブルを抜き差ししたくないし、CPU に無用な負荷をかけたくない
- MacBook (Hawk) を外から持ち帰ったら、WLAN ごしに、半自動でバックアップを始めたい
ちょっと調べた限りでは、なかなか大変なように見えたが、 やってみると意外にスンナリ行った……
pi@raspi06:~$ sudo apt-get install netatalk pi@raspi06:~$ apt list --installed netatalk Listing... Done netatalk/stable,now 2.2.5-1+b1 armhf [installed] pi@raspi06:~$ sudo mkdir /home/share pi@raspi06:~$ sudo chmod 777 /home/share pi@raspi06:~$ nano /etc/netatalk/AppleVolumes.default pi@raspi06:~$ tail /etc/netatalk/AppleVolumes.default ..... # The line below sets some DEFAULT, starting with Netatalk 2.1. :DEFAULT: options:upriv,usedots # By default all users have access to their home directories. # ~/ "Home Directory" #1) /home/share "Time Capsule" options:tm #2) # End of FileListing... Done pi@raspi06:~$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 1.8T 0 disk ├─sda1 8:1 0 200M 0 part ├─sda2 8:2 0 465.8G 0 part ├─sda3 8:3 0 465.9G 0 part ├─sda4 8:4 0 465.8G 0 part #3) └─sda5 8:5 0 465.1G 0 part mmcblk0 179:0 0 29.7G 0 disk ├─mmcblk0p1 179:1 0 56M 0 part /boot └─mmcblk0p2 179:2 0 29.7G 0 part / pi@raspi06:~$ sudo mkfs.ext4 /dev/sda4 pi@raspi06:~$ sudo chmod 777 /home/share pi@raspi06:~$ sudo mount /dev/sda4 /home/share pi@raspi06:~$ sudo systemctl restart netatalk
- #1) この行はコメントアウト(しなくても問題無さそうだが)
- #2) 追加したのはこれだけ。"Time Capsule"
が、Time Machine から見える(ちょっと紛らわしい名前にしてしまったかも。)
options:tm
がミソ。 - #3) この USB-HDD は、Mac OSX で partition を切った。 使ってないこの partition を以下で、ext4 にフォーマットして使う
最初のフルバックアップに 8 時間どころか、都合 10 時間もかかったが、 とりあえずは完了した。
色々右往左往したが、ポイントは
- netatalk-2.2.2 (Ubuntu-14.04) でも、samba でもダメで、 netatalk-2.2.5 (Raspbian Jessie) が必要
- mount する partition は、Linux FS (ext3 か ext4) でないといけない
- 'Select Disk ...' で聞かれる、user/password は、Raspi のアカウントのそれ (この場合は、pi)
- マウントポイント (この場合、/usr/share/) は、 上記ユーザが、読み書き実行できないといけない
2015-10-25 (Sun): 自宅サーバのバッテリを交換
ThinkPad X200 + Ubuntu-14.04LTS
X200 を自宅サーバにしてから、もう 2年になるのかぁ。最初の頃 (Ubuntu-13.10) は結構色々なトラブルが有ったが、 Ubuntu-14.04 にしてからの 1年半は、問題らしい問題は一度も無かったように思う。ただ、X200 は 2008 年に買ったものなので、もう 7 年になる。X23 の例からすると、そろそろ乗り換えを考えても良い頃かも…… という事で、色々な「野心的な案」を検討してみた……
- OS を freeBSD に: OSX では専ら MacPorts なので、FreeBSD にしたら、port コマンドでスイスイ…… と長らく憧れていたのだが、今回何年ぶりかで Fusion に最新版 (-10.2) を入れてみた。 PC H/W に直接インストールしていた頃は、四苦八苦した記憶があるが、 今回はすんなりインストールが完了した。 Xorg が入ってない、というのにまず驚くが、「まあ、サーバにするのが目的だし」 と自分に言い聞かせて次に行こうとするが、パッケージ管理は pkg を使うのだった。他にも、(sudo も su も使えない等) Linux との違いは多々あるが、それらは追々修正できるだろうが、pkg が MacPorts の port とあまり似ていないのはどうしようもなさそうで、 とってもガッカリした。で、早々に諦めた。
- H/W を Mac に: Notebook をサーバとして使うと LCD が宝の持ち腐れとなるのが癪だった。 一方値段の割に Mac-mini が素晴しいので、 OSX の MacPorts のコマンド群を使ってサーバにするか、もしそれが難しければ、 Fusion で Linux を入れて……。しかし、これ、OSX の元からある機能とのバッティングが心配。(例えば、mDNS が、 dhcpd とうまく協調してくれない。)何より、UPS が要る。
- MacBook: 今の MacBook Air をサーバに。しかし、これ、 上の OSX 共通の問題に加えて、 1) メモリが 2GB しか乗ってない、 2) SSD が 128G しかついていなくて、かつ、そのうちの 15% しか空きがない、という問題が。
- VPS: ちらちらと横目で見ていたが、なかなか良さげ。 一月 1700 円くらいで、2GB/200GB のサーバが持てる(現在の X200 は、 2GB/160GB) 。各社プライスパフォーマンスは似たりよったりだが、 さくらの VPS さんの「OS は何でも OK」というあたりに惹かれている。 最初は「安いなあ」と感心したものの、12 万円の ThinkPad を 7 年保たせたら、トントンになる……
バッテリが逝ってしまった
などと思い悩んでいたのだが、先週だったか、 件の ThinkPad のバッテリインジケータが、 オレンジの点滅になっているのに気がついた。 これはしかし "Low Battery" の意味なので、然程緊急の問題とも思っていなかった。 が、一昨日ログインしたついでに、調べてみたら、
fukuda@lark:~% upower -i /org/freedesktop/UPower/devices/battery_BAT0
native-path: BAT0
power supply: yes
updated: Fri 23 Oct 2015 06:27:49 PM JST (23 seconds ago)
has history: yes
has statistics: yes
battery
present: yes
rechargeable: yes
state: charging
energy: 0 Wh
energy-empty: 0 Wh
energy-full: 0 Wh
energy-full-design: 0 Wh
energy-rate: 0 W
percentage: 0%
capacity: 100%
となっているではないか……
これは、もうバッテリが死んでいるという事なので、
今停電したら、もしくは、電源ケーブルを抜いたら、
即クラッシュする事になる。
(大昔 X23 で、態々試して確認済み——好奇心に勝てずに、
ついつい電源ケーブルを抜いたら、クラッシュ……)
慌てて上の「新サーバオプション」を前倒しで実現する事を考えたが、 「停電したらクラッシュ」に背中を押されて、 とりあえずバッテリを新しくする事にした。 今回は、来年の四月まで保てばいいや、という事で互換モデル (World Plus 製) にした。金 4000 円也。
発注の翌日に届いて(さすがアマゾンさん)、 電源ケーブルを差したまま、バッテリを入れ替え、様子を見てみると
fukuda@lark:~% upower -i /org/freedesktop/UPower/devices/battery_BAT0
native-path: BAT0
vendor: SANYO
model: 42T4646
serial: 8030
power supply: yes
updated: Sun 25 Oct 2015 04:04:22 PM JST (0 seconds ago)
has history: yes
has statistics: yes
battery
present: yes
rechargeable: yes
state: charging
energy: 28.47 Wh
energy-empty: 0 Wh
energy-full: 48.6 Wh
energy-full-design: 47.52 Wh
energy-rate: 34.337 W
voltage: 11.816 V
time to full: 35.2 minutes
percentage: 58%
capacity: 100%
technology: lithium-ion
History (charge):
.....
という事で、目出たく復旧した模様。
この電池交換は、自宅サーバ更新とは一応別の「応急処置」のつもりだったが、
こうして 4000円也をはたいてみると、来年の
4月に、do-release-upgrade
で、さくっと 16.04LTS
にして、このままさらに一年くらい使えるかな……なんてスケベ心が出てきた。
とすると、次に「問題」が出るとしたら、それは多分 HDD
がらみなので、いずれにせよ full-backup の心配をせねば。
2015-10-21 (Sun): Python/NumPy Update (その 2)
「行列演算」再訪
先の記事では、ndarray の行列の掛け算の二項演算子'@'
が導入された……という話を書いたが、我ながら「頓珍漢」だったなぁ。
というのも、NumPy には、ndarray に加えて、matrix という class
も有って、そちらでは '*'
が、
普通に行列の掛け算になっている……
In [1]: import numpy as np In [2]: A = np.matrix([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) In [3]: A Out[3]: matrix([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) In [4]: x = np.matrix([1, 1, 0]) In [5]: x Out[5]: matrix([[1, 1, 0]]) In [6]: x.T Out[6]: matrix([[1], [1], [0]]) In [7]: A * x.T Out[7]: matrix([[ 1], [ 7], [13]]) In [8]: A @ x.T Out[8]: matrix([[ 1], [ 7], [13]]) In [9]: A_arr = np.array(A) In [10]: A_arr Out[10]: array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])また、ベクトルの転置も(
reshape()
して云々という手間をかけずに)自然にできている (In/Out[9])。
つまり、'*'
で行列の乗算をしたければ、
numpy.matrix でやれば良い……。それを、また ndarray
に戻すのも簡単。それでは何故 '@'
が必要なのか、という事になるが、それがすっきりと納得できず、
いい加減にお茶を濁したのだった。
PEP 465 には、色々「必要性」が書いてあるが、今一納得しきれなかった。 しかし、色々弄っているうちに、「まあ、それも良いかな」から、 はっきり「これは確かに嬉しいかも」と思えるようになった。
つまり
-
np.dot(A, B)
は煩雑になるので何とかしたい。 -
'*'
の overloading で、 両方の行列乗算を表すようにする、というのも一案。 しかし、それではA * B
とあった時、A, B
がどういう dtype なのかを知らないと、要素毎の乗算なのか、 行列乗算なのか直ぐには解らない。 - 新しい
'@'
を導入する事で、 必ず「行列乗算」である事を示せる。numpy.matrix についても'@'
が行列乗算を表すので (上のリストの In/Out [8])、これを必ず使う事にすれば、A, B
の dtype にかかわりなく、A @ B
とあれば、行列乗算であるとすぐに解る。
'@'
導入のメリットが、
「記号選定」への違和感を上回ると納得できた。
Axis の「順序」
これに関する「違和感」も、どう言い表せばよいのかちょっと悩んでしまう。 NumPy の ndarray や matrix の Axis というのは、 つまるところ「行」とか「列」とかの、Index が伸びて行く方向の事 (「行ベクトルは」、列軸だけを持つ事に注意。) 端的に言うと、reshape()
method の引数や、
.shape
attribute
の並び方の問題。で、二次元配列(行列)までは、どちらも、
(行, 列) となっている。問題はこの先で、
次の次元(とりえあず「高さ」次元)を加える時、(FORTRAN
からの連想だと)(行, 列, 高) となってしかるべきだと思うが、
NumPy では(高, 行, 列) となるのだった。
順番が逆というより、一貫していないように思える……
FORTRAN の三次元配列が、例えば A(I, J, K) と表わされるなら、
NumPy のは(A(K, J, I) ではなく)、A(K, I, J) となる……のが不満だと。
In [52]: A2 = np.arange(12).reshape(3, 4) In [53]: A2 Out[53]: array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) In [54]: A3 = np.arange(24).reshape(2, 3, 4) In [55]: A3 Out[55]: array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]])
しかし、「曰く言い難い違和感」をこのように整理してみると、自分にとって「Axis
の順序が憶え難い」という事の他には不具合は無さそうな気がしてきた。
reshape()
に際しては、(高, 行, 列)
の順序で、サイズを指定すれば良いのだし、
indexing もこの順序で OK。
transpose()
に際しては、(0, 1, 2) が (高, 行, 列) で、
その行と列を入れ替えるなら、(0, 2, 1) とすれば良い、という塩梅。
In [56]: A3[1, :, :] Out[56]: array([[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]) # 「高さ」方向の二つ目の要素を切り出した In [57]: A3[:, :, 1:3] Out[57]: array([[[ 1, 2], [ 5, 6], [ 9, 10]], [[13, 14], [17, 18], [21, 22]]]) # 「行」方向の二つ目と三つめの要素を切り出した In [58]: A3.transpose() Out[58]: array([[[ 0, 12], [ 4, 16], [ 8, 20]], [[ 1, 13], [ 5, 17], [ 9, 21]], [[ 2, 14], [ 6, 18], [10, 22]], [[ 3, 15], [ 7, 19], [11, 23]]]) In [61]: (A3.transpose() == A3.transpose(2, 1, 0)).all() Out[61]: True # ディフォルトが 0-軸(列) と 2-軸(高さ)の入れ替えになっている # (.all() は、要素毎の比較の結果の AND を取る、という意味) In [62]: (A3.transpose() == A3.T).all() Out[62]: True # .T アトリビュートは上のディフォルトと同じ In [63]: A3T = A3.transpose(0, 2, 1) # 行と列を入れ替える変換 In [64]: A3T.shape Out[64]: (2, 4, 3) In [65]: A3T @ A3 Out[65]: array([[[ 80, 92, 104, 116], [ 92, 107, 122, 137], [ 104, 122, 140, 158], [ 116, 137, 158, 179]], [[ 800, 848, 896, 944], [ 848, 899, 950, 1001], [ 896, 950, 1004, 1058], [ 944, 1001, 1058, 1115]]]) # 2 つの (4, 3) 行列と 2 つの (3, 4) 行列の積の結果、二つの (4, 4) # 行列ができている
2015-10-18 (Sun): Python/NumPy Update
ずっと Django の事を書いて来ているが、でも、これはどうも「Python の話」という気がしない。(ホントは Django に飽きてしまった、もしくは、その Learning Curve の急峻さに嫌気が差したのかも。) では、何にぞくぞくするか、と言われるとやはり NumPy だろう。 先の McKinney さんの本には、NumPy の概要を纏めた章も有って、 久方ぶりに brush-up した。Ndarray の乗算
Python-3.5.0 の What's New に、"a new matrix multiplication operator: a @ b" というのが出ていた。当初、 「これを実装したモジュールはまだ無い」とあったが、程なく、 「NumPy 1.10 はこれをサポートする予定」との記述に変わった。 これはちょっかいを出さない訣には……「Python-3.5 にするのはもっと先」と決心した筈なんだけど、pyvenv + pip なら簡単に試せそうなので、そっちでやってみた。
fukuda@falcon:~% sudo port install python35 fukuda@falcon:~% pyvenv-3.5 pve35 fukuda@falcon:~% cd pve35 fukuda@falcon:~/pve35% . bin/activate (pve35) fukuda@falcon:~/pve35% pip-compile ..... gnureadline==6.3.3 # via ipython ipython==4.0.0 matplotlib==1.4.3 numpy==1.10.1 ..... (pve35) fukuda@falcon:~/pve35% pip-syncこれだけで、準備は完了。早速 iPython を立ち上げて、
(pve35) fukuda@falcon:~/pve35% ipython
Python 3.5.0 (default, Sep 15 2015, 23:58:24)
Type "copyright", "credits" or "license" for more information.
IPython 4.0.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: import numpy as np
In [2]: A = np.arange(9).reshape(3, 3)
In [3]: A
Out[3]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [4]: B = np.arange(-4, 5).reshape(3, 3)
In [5]: B
Out[5]:
array([[-4, -3, -2],
[-1, 0, 1],
[ 2, 3, 4]])
In [6]: A * B
Out[6]:
array([[ 0, -3, -4],
[-3, 0, 5],
[12, 21, 32]])
In [7]: np.dot(A, B)
Out[7]:
array([[ 3, 6, 9],
[ -6, 6, 18],
[-15, 6, 27]])
In [8]: A @ B
Out[8]:
array([[ 3, 6, 9],
[ -6, 6, 18],
[-15, 6, 27]])
となるのを確かめた。つまり、A * B
は、要素ごとの掛け算、
numpy.dot(A, B)
と A @ B
は、行列同志の掛け算となっている。(この後の方が、
Python-3.5 と NumPy-1.10 による今回の新機軸。)
ちなみに、Numpy-1.9.2 ではエラーとなる——MacPorts の py35-numpy (-1.9.2)
で、実験してみた
fukuda@falcon:~% python3.5
Python 3.5.0 (default, Sep 15 2015, 23:58:24)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.56)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.__version__
>>> '1.9.2'
>>> A = np.arange(9).reshape(3, 3)
>>> B = np.arange(-4, 5).reshape(3, 3)
>>> np.dot(A, B)
>>> array([[ 3, 6, 9],
[ -6, 6, 18],
[-15, 6, 27]])
>>> A @ B
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for @: 'numpy.ndarray' and 'numpy.ndarray'
NumPy を最初に習え憶えた頃、A * B
が、行列の要素ごとの掛け算だった事にかなり違和感を感じた。
ちょっと後になって、これは、Universal Function
を素直に表現するため、というか、それと混在するためには自然な方法だ、
と納得した——A +/- B, A ± k, k * A
(k
はスカラ) 等と並べれば、 A * B
が要素ごとの掛け算としたい、という気持はまあ解る。
ただ、なぜ '@'
なのか、という違和感が拭えない……
それでも、まあ、infix operator (C で言うなら、binary operator?)
の効用は大きいだろうから、この違和感もそのうち消えるだろう。
なにしろ、
S = dot((dot(H, beta) - r).T, dot(inv(dot(dot(H, V), H.T)), dot(H, beta) - r))のように書かざるを得なかったものが、
S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)とできるのだから。(例は Python-3.5 の What's New から取った。)
Vector と Array
この他にも「最初ワケワカだったけど今はなんとなく使えている」 という例はいくつか有って、その大物の一つは ベクトル (vector) の扱い。線形代数では、例えば と書いた時の は列ベクトルで という意味。行ベクトル については、これは、 すなわち、 となる。こんな事は基本のキなので、NumPy 使えば、ひょいひょいとやれる筈……
In [4]: A = np.arange(9).reshape(3, 3) In [5]: A Out[5]: array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) # iPython の Array の表示は美しい In [6]: x = np.array([1, 1, 0]) # x は行ベクトル (?) In [7]: A @ x.T Out[7]: array([ 1, 7, 13]) # x.T が列ベクトルなので、 上の Ax を計算している In [8]: np.dot(A, x.T) Out[8]: array([ 1, 7, 13]) # np.dot (既存の演算)でも確認 In [9]: x @ A.T Out[9]: array([ 1, 7, 13]) # 行ベクトルでも、正しい答が In [10]: x @ A Out[10]: array([3, 5, 7]) # 転置を忘れると答が違う、ここまでは So Good In [11]: A @ x Out[11]: array([ 1, 7, 13]) # あれ、行ベクトルのままでも同じ結果が In [12]: x.T Out[12]: array([1, 1, 0]) # そもそも、転置が起きていない……で、もうワケワカ…… 私の「当惑」を整理すると概略このようになるだろうか。 後知恵だが、Out[7] で答が「列ベクトル」になってないあたりで、 「おかしい」と気付くべきだろうが、行ベクトルを入れて、 行ベクトルが出てくる(Out[11]) ので、まあ、こういうものかな、 と納得して、その後はずっと使ってきた。
しかし、
Infix Operator の '@'
が、ほんとに np.dot()
と等価かどうかを確かめている過程で、
どうもこのあたりが気色悪く思えてきて、ちょっと追及してみた。
自分の混乱の根源は
「ndarray (n 次元の array) は『行列』とは違う」のを忘れていた事に尽きそう。
行列としての演算(掛け算、転置等)は、
オペランドの
ndarray が、双方ともに二次元の時だけ意味を持つ。
言い換えれば、array([1, 1, 0])
は(行列の演算が適用される)「行ベクトル」ではない。
x をちゃんとした行ベクトル(1 行 n 列の行列)とするところから始めると
In [14]: x = np.array([1, 1, 0]) In [15]: x.shape Out[15]: (3,) # x は 1 次元の array。'(3,)' は要素数 1 のタプルを表わす。 In [16]: xrow = x.reshape(1, 3) In [17]: xrow.shape Out[17]: (1, 3) # これで、1 行 3 列の行列(行ベクトル)になった。 In [20]: xrow Out[20]: array([[1, 1, 0]]) # '[' が二重になっている。 In [21]: xrow.T Out[21]: array([[1], [1], [0]]) # 転置の結果もちゃんと列ベクトルになっている In [22]: A @ xrow.T In [23]: A = np.arange(9).reshape(3, 3) # あらためて、Ax を計算 In [24]: A @ xrow.T Out[24]: array([[ 1], [ 7], [13]]) # 結果もちゃんと列ベクトルになっている In [26]: xrow @ A.T Out[26]: array([[ 1, 7, 13]]) # xrow A^T も期待通りの値となっている。という具合に、全て「期待通り」となる……。
それではなぜ紛らわしい(結果だけは正しい)「現象」が表われたのか…… これは勿論 "broadcasting" のせい(というか、お陰)。 k 行 l 列の行列 A(A.shape == (k, l))と B (B.shape == (m, n)) の掛け算が意味を持つためには、 l = m でないといけない。 ここまでは素直に理解できる。ここで、もし B が行列でなく、 一次元の array の場合(つまり B.shape == (m,) の場合) (m,) => (m, 1) とする事によって掛け算を実行、 その結果の (k, 1) から、1 を抜いて、k 要素の一次元 array に戻す、という事をやっていた訣だ。
以上を明示的に書くと、
In [30]: A @ x Out[30]: array([ 1, 7, 13]) In [31]: (A @ x.reshape(3, 1)).reshape(3) Out[31]: array([ 1, 7, 13]) In [32]: x @ A.T Out[32]: array([ 1, 7, 13]) In [33]: (x.reshape(1, 3) @ A.T).reshape(3) Out[33]: array([ 1, 7, 13])となる。[31] では、reshape(3, 1) となっているのに、 [33] で、reshape(1, 3) となっているところが巧妙なところ。 (言語仕様では「外側に次元を追加する」となっている。)
分ってしまえば、So what? (そう、それで?)と言われそうな話だが、 これ(broadcast) で謎解きできるミステリーは幾つかある。 たとえば vector 同士の掛け算……
In [55]: xrow.T @ xrow Out[55]: array([[1, 1, 0], [1, 1, 0], [0, 0, 0]]) In [56]: xrow @ xrow.T Out[56]: array([[2]]) In [57]: x @ x Out[57]: 2最後の例では、(3,) × (3,) ⇒ (1, 3) × (3, 1) ⇒ (1, 1) (直前の結果と同じく行列)とした後、 (両方の「次元」を剥ぎ取って)無次元(すなわち、スカラー)としている。 結果として、より忠実な「内積」を実現している訣だ。
2015-10-16 (Fri): iPython 再訪
ちょっと前に、Wes McKinney, "Python for Data Analysis" を買って積読になっていたが、ひょんなキッカケで、その中の iPython と NumPy にかかわる章を読んだ。特に新しい事は書かれていないが、 要領良く纏まっていて、要点を思い出す(自分の勘違いを訂正する) のにとっても役に立った。使わなかった理由……
iPython に限らず、IDLE や、Emacs 上の Python-mode (の py-shell) などを試して、また実際に何度か使い始めてみたものの、その都度「立ち消え」 になって、今では "coloring のみの Emacs/python-mode"と、 Terminal.app 上の純正 interactive shell だけ、に戻っている。 (退化と言えば退化だが、Django の DEBUG_MODE が素晴らしいので、 これで十分だった……)しかし、思い返せば、「iPython……なんだかなぁ」という感想は、 かなり不運な(実は頓馬な)勘違いから来ているようにも思える。
- IronPython と取り違えていた: 大昔の事だが、折角 S田氏が「(Enthought の) iPython いいですよぉ」って勧めてくれたのに、この勘違いのせいで無視してしまった。 いくら IronPython にがっかりした直後だったとは言え、何とも頓馬な……
- Matplotlib/NumPy との強すぎる「連携」が嫌: iPython のウリの一つに、
(pve35) fukuda@falcon:~/pve35% ipython --pylab
として立ち上げておけば、NumPy や matplotlib が自動で import され、いきなり、array([[1, 1], [2, 2]])
とか、はたまた、plot()
などとやれてしまう、という事がある。 また、それに加えて、np.array(), np.plot()
も OK :-) 一見便利そうだが、NumPy も matplotlib.pyplot も非常に多量の method や attribute を含むから、 「ワケワカ」の元になりがち。 - Notebook が OSX では使えない: ipython notebook は、当初から互換性が今一だった——必要とする library の多さからして無理もない? 現在では相当改善されているが、 OSX では、matplotlib のグラフが inline で表示されない。 (これでは、態々 notebook を使う意味がない……) pyvenv-3.5 で新たに環境を作って確認しようとしたら、そもそも notebook を入れたら、pip-compile でエラーになる。
- prompt がダサい: オリジナルのシェルに比べて、何とも洗練されてない。 in と out の区別は本当に必要だろうか?私は個人的には、CPython のオリジナルのプロンプト ('>>>' (input), '' (output)) で十分だと思っている。 あと、無用な空行が入るのも「何だかなぁ」である。
再挑戦の結果
先になって「また止めてしまう」という可能性も勿論有るが、今のところは、 使い続けたい、と思っている。 それには、- インストールは pyvenv 内で、pip-compile, pip-sync で行う。 (requirements.in に ipython の一行を入れる。)
- 当面 python-3.5 (pyvenv-3.5) で notebook は使わない
- ipython --pylab も使わない。(どうやら、--pylab は「推奨」から外されたようだ。)
こうすれば、大体上の教科書に書いてある「メリット」全般を享受できる。 とりわけ次のような事に感銘を受けた。
- array の表示が、綺麗に「行列」の形になる事、
さらに大きい行列に関しては、見易く「中抜き」してくれる事
In [8]: arr = np.arange(1200).reshape(30, 40) In [9]: arr Out[9]: array([[ 0, 1, 2, ..., 37, 38, 39], [ 40, 41, 42, ..., 77, 78, 79], [ 80, 81, 82, ..., 117, 118, 119], ..., [1080, 1081, 1082, ..., 1117, 1118, 1119], [1120, 1121, 1122, ..., 1157, 1158, 1159], [1160, 1161, 1162, ..., 1197, 1198, 1199]])
- 行毎ではなく、ブロック単位で編集ができる事(
def func(): ...
とか、for i in range(n): ...
のブロックを呼び出して、部分的に編集できる)In [10]: def myadd(a, b): ....: c = a + b ....: return c ....: In [11]: myadd(1, 2) Out[11]: 3 # In [12]: の後で、Ctrl-p とやると、In [10] で入力したブロック全体が呼び出され In [12]: def myadd(a, b): c = a + b return c + 1 # のように、部分的に編集できる ('+ 1' を追加した)
この例はトリビアルだが、 (関数を含む)ブロックが長くなってくると、これはとっても有難い。 ただ(欲を言うなら)呼び出した後の方も(最初の入力時同様に) インデントがきちんと表示されたら、もっと嬉しいかも…… -
! command
として、shell command が起動できる -
%cpaste
として、(例えば)Emacs からの script の一部をそのまま copy/paste して実行できる
これらの(言わば「今更」の)メリットに加えて、 私の特殊事情の下での「なかなかやるね」は
- GNU readline にまつわる不透明さが解消されている——OSX
の下でも pyvenv の条件下にあるかどうかに関係なく、行(ブロック)編集、search
が可能。これは「不透明さが解消された」というより、従来の readline module
(GNU readline だったり libedit だったりする)とは別の gnureadline module
を使うようになったと言うべきか?
そもそも、~/.python_history の代りに、
(pve35) fukuda@falcon:~/pve35% ls ~/.ipython/profile_default/history.sqlite -l -rw-r--r-- 1 fukuda staff 81920 Oct 15 17:51 /Users/fukuda/.ipython/profile_default/history.sqlite
などという sqlite の DB file を使っているようだ。(Binary なので、lv や Emacs では開けない。) - Django の
python manage.py shell
で、ipython が立ち上がる。(何の設定も要らない。 むしろ元に戻すのにどうしたらよいか解らない。:-)(PyVenv) fukuda@falcon:~/PyVenv/wrm_cwt% python manage.py shell Python 3.4.3 (default, Aug 26 2015, 18:29:14) Type "copyright", "credits" or "license" for more information. IPython 4.0.0 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython's features. %quickref -> Quick reference. help -> Python's own help system. object? -> Details about 'object', use 'object??' for extra details. In [2]: from tts.models import Area In [3]: areas = Area.objects.all() In [4]: area = areas.last() In [5]: area. area.DoesNotExist area.objects area.MultipleObjectsReturned area.party_set area.area_name area.pk ... area.get_tag_order area.timezone area.get_timezone_display area.unique_error_message area.id area.userlog_set area.latitude area.validate_unique area.longitude area.zoom In [6]: area.area_name Out[6]: 'Kita-yatsu'
つまり、通常の Python の Interactive Mode と同様に、 Django の Query Set が扱え、また、models.py で定義されているクラスの attribute/method の扱いも問題無い。
245/1,780,911 Taka Fukuda Last modified: 2016-01-19 (Tue) 10:42:18 JST