数理的手法を使いやすくするためのソフトウェア開発

科学技術計算とデータサイエンスについて

iCloud / Google Drive と git を一緒に使うとリポジトリがおかしくなることがある?

自宅で文書ファイルやソースコードをバージョン管理、バックアップしたり、複数PCで同期させるための 方法を検討しています。 初めは、iCloud あるいは Google Drive にgitリモートリポジトリを置くのが手軽で良いのかも、 と思っていたのですが、危険もあるようです。

1. 背景:iCloud / Google Drive のファイル共有機能は便利だが、バージョン管理機能は貧弱

複数のPCやデバイスの間でファイルを共有するために、 iCloud Drive や Google Driveを私は使っていて、この機能については特に不満はありません。

しかし、git のようなバージョン管理ができないのが残念です。 iCloudファイル復元できるだけであり、Google Driveでは、バージョンを遡るくらいのことはできますが、 下書き用のブランチと、メンテナンス用のブランチを切り替えることはできません。

2. 手法:iCloud / Google Drive を gitリモートリポジトリとして使うのは簡単

そこで、これらのクラウドストレージをgitとともに使う方法を調べてみると、意外と簡単にできることがわかりました。

How to Add iCloud as a Git Repo | MacStadium Blog

Using GIT with Google Drive – a Tutorial

iCloud Drive についてもGoogle Driveについても、やり方は同じで、次の2ステップです。

(1) クラウドストレージ上に git リモートリポジトリを作成
$ mkdir ${CLOUD_STORAGE}/gitRepo/
$ git init --bare ${CLOUD_STORAGE}/gitRepo/your_project.git

ここで、${CLOUD_STORAGE} には、 クラウドストレージに同期させているディレクトリの名前を指定します。

例えば、macOS (ver. 12.4) で Document フォルダを iCloud Drive と同期させている時には、 ${CLOUD_STORAGE} として ~/Library/Mobile\ Documents/com~apple~CloudDocs/を指定すれば良いです。 また、 "Google Drive for Desktop"をインストールして、ローカルなHDDの /Volumes/GoogleDrive/マイドライブ/ ディレクトリを Google Driveと同期させている時には、 そのディレクトリ名を指定すれば良いです。

(2) 作成したリモートリポジトリにローカルプロトコルでアクセスできるように設定

すでに、リモートリポジトリ your_project.gitに対応する、 ローカルリポジトリがあるときには、次のようにします。

$ cd ${YOUR_PROJECT_DIR}
$ git remote add origin ${CLOUD_STORAGE}/gitRepo/your_project.git

ここで、${YOUR_PROJECT_DIR}はローカルリポジトリディレクトリ名です。

そして、git remote add originでは、 リモートリポジトリのURLとしてディレクトリパスを指定します。 (普通は URLをhttps:// ...ssh:// ...のように指定しますが、 同じ計算機のなかにリモートリポジトリがあるときにはディレクトリパスを指定して、 gitはローカルプロトコルでリモートリポジトリにアクセスするようにします。 そして、クラウドストレージ上のリモートリポジトリは、 同じ計算機のなかにあるかのように扱えるので、ディレクトリパスを指定するのです。)

これによって、git push origin mastergit pull origin masterなどは、 クラウドストレージ上のリモートリポジトリに対して行われるようになります。

ちなみに、リモートリポジトリ your_project.gitからローカルリポジトリを複製する時には、次のようにします。

$ git clone ${CLOUD_STORAGE}/gitRepo/your_project.git

3. 考察:クラウドストレージとgitを混ぜるとトラブルが生じるのか?

3.1 iCloud Drive + git の危険性は否定できない

しかし、よくよく調べてみると、iCloud Drive をgit とともに使ってみてトラブルが生じた(余計なファイルやディレクトリが現れた)という報告が見つかりました。

iCloud管理下のフォルダでgitリポジトリをクローン ⇄ rm -rf 繰り返したら、覚えのないファイルが生成されつづけて困った話 - 自分にやさしく学ぶプログラミング

Xcode 11 + project with git + iClo… | Apple Developer Forums

iCloud Driveは何でもかんでも同期されるわけじゃないのね|nnamm.work

3.1.1 トラブルの原因は、iCloudのファイル同期とgitのファイル更新が衝突することがあるから

そして、トラブルシューティングのアドバイスを求める質問に対して、 クラウドストレージとgitを混ぜて使うのは勧められない、と答えている人がいました。

macos - ICloud Drive Desktop Sync vs. Git - deleted files reappear and duplicates with number suffixes - Stack Overflow

Short Answer: Keep your repository folders outside of your iCloud Drive-synced folders, and you should be fine. To be safe, do not combine VCS and file-syncing services together for the same directories/files. Use Github/GitLab/Bitbucket/etc. for synced access and centralised safekeeping.

...
Even Longer Answer: ... In the particular case of the 'iCloud Drive + git' pair, we have a deadly combination: git is very fast at make sweeping changes to entire directory structures, and iCloud Drive is notoriously bad at detecting what has actually changed correctly - and is also very slow at syncing. This means that as git goes about switching branches and updating your working tree, iCloud Drive is likely to wrongly detect that files have changed, when they haven't. It will then tag these files for syncing. But because it is extremely slow at syncing, by the time it's halfway making its first duplicate copies, you might have already made another git change to your repository - which will cause you to now have 'file 3', and then 'file 4' and so on.

Hopefully this might change in the future, but in the meantime, the safest solution is to simply NOT keep your version-controlled repositories in any folder that is automatically synced. In this particular case, if you keep your repositories on any folder that is not 'Documents' or 'Desktop' - and not watched by iCloud Drive - then you should not have an issue with git.

上記回答のなかでは、トラブルが起こるメカニズムも説明されています。 私はiCloud やgitの内部動作に詳しくはないのですが、説明されているようなメカニズムなら、 gitリポジトリ内部のファイル更新と iCloudのファイル更新検知が協調動作しないために、 報告されているように妙なファイルやディレクトリがiCloudによって作られることもありえる、 と思えます。

3.1.2 iCloudがうまく同期できないファイルやフォルダがある

あと、 Appleは「iCloudに appフォルダを入れるべきでない」と公式に注意していて、 .gitは appフォルダのようなものだから、gitリポジトリiCloudに入れるべきではない、という意見もありました。

github - Can Git and iCloud Drive be effectively used together? - Stack Overflow

No, they shouldn’t be used together.

* Apple says “You shouldn’t store app folders, libraries, or .tmp files in iCloud Drive.” .git is an app folder.

ただ、なぜ .gitディレクトリが appフォルダのようなものと見なせるのかは、この投稿に書かれていませんでした。

3.2 Google Drive + git のトラブルは回避可能?

ただ、Google Drive + git については、 iCloud Drive + git のような、確かなトラブル報告は見つかりませんでした。 また、私が Google Drive + Colab + git を一緒に使っていたとき、 別にトラブルには遭遇しませんでした。

それでも、Google Driveをgitと混ぜて使うことの質問に対して、 混ぜて使うのは勧められない、と答えている人はいました。

git - Can I push/pull directly from my google drive online? - Stack Overflow

No, you can't. ...I would also suggest against Google drive/Dropbox based solutions, and go for a git hosting solution instead. ...

... you can put the bare repository inside your local Google Drive/Dropbox folder and work with that, however, there are caveats. The cloud services have their own systems for merging conflicts, and that doesn't really work with git. ...

しかし、 Using GIT with Google Drive – a Tutorial

There is one major caveat that you should know about (not a show stopper, but important to have control over). On some Windows machines, Google Drive can have trouble to synch all the Git files in one go. There’s a simple solution, you just shut down Google Drive and restart it again. It then re-synchs and the remaining files get synched. It’s important to not forget to check this after each git push since otherwise you can mess up the git project files on Google Drive and you’d be left with a mess.

のように、Windows PCでは Google Drive + git でトラブルが起こることが知られているものの、 その回避策はあるようです。

また、

Git + Google Drive = Simple Git Host | by Laura Taylor | Medium

When sharing the Git repository, collaborators should coordinate ‘push’ and ‘pull’ operations to avoid sync conflicts which could leave the Git repository in an unstable state.

のように、Google Drive上のリモートリポジトリを操作する時には、 リモートリポジトリの更新とGoogle Driveのファイル同期が衝突しないように、 複数のpush やpushの操作が重ならないように気をつけるべきで、 さもないと、リポジトリが不安定な状態に陥るようです。

4. どうするか: gitホスティングサービスの無料プライベートリポジトリ

クラウドストレージとgitを混ぜて使うのは、安全なのでしょうか、危険なのでしょうか? 調べてみると意見が分かれるようです。 iCloudについては、トラブルに遭遇したことがないという人はいますが、 トラブル事例を見る限り危険性は否定できないと思います。 そして、gitリポジトリのなかに余計なファイルやディレクトリが勝手に作られるというトラブルは、 かなり重大に思えます。 他方で、Google Driveについては確かなトラブル報告が見つからなかったので、 注意すればトラブルを回避できるのかもしれませんが、不安は残ります。

なので、安全性と確実性をとるなら、 クラウドあるいはオンプレミスのgitホスティングサービスのほうが良いのかもしれません。

GitHub: Where the world builds software · GitHub

Bitbucket | Git solution for teams using Jira

The One DevOps Platform | GitLab

Mac miniで始める「GitLab」入門! | ai-lab

ただ、オンプレミスのGitLabサーバーを構築するのは、 クラウドストレージとgitを混ぜて使うより、はるかに手間がかかるので、悩ましいところです。 しかし、今や、GitLab.com と Bitbucket.org だけでなく、 GitHub.com でも、無料でプライベートリポジトリを作れる ので、 非公開のソースやドキュメントを扱いたい場合でも、 これらのgitホスティングサービスを利用する方がよさそうです。

(それでも、 盗まれたOAuthユーザートークンでGitHubリポジトリからデータ奪う攻撃発生 | TECH+ のようなことが起きているので、重要度の高いgitリモートリポジトリは自宅内のPCに置いて、 外部インターネットからアクセスされないようにしておこうと思います。)

macOS 12.3.1 にLinuxコマンドをインストールするために

tree コマンドがなかったので、brew install tree としてみましたがエラーが出たので、 xcode のインストールから始めて、homebrew を更新しました。

参考

【Mac】treeコマンドのインストール - Qiita

Xcode インストール

tree コマンドのインストールは、後述のcommand line tools(CLT) だけでできるそうなので、 xcodeはまだ必要ないのかもしれません。

しかし、統合開発環境として名高いxcodeが、 これまでLinuxで慣れ親しんできたEclipseVisual Studio Codeと比べてどうなんだろうか、 と気になりました。

それで、App Store を立ち上げて、xcode を検索。「入手」をクリック。バージョンは Xcode 13.4 。 なんとインストーラーのサイズ 12.6Gbで、ダウンロードとインストールに一晩(12時間)かかりました。orz 

余計な時間をかけてしまったかも。。

ただ、 CommandLineToolsとXcode - Qiita

によれば、 ver. 6.1 以降は App Storeから xcode をインストールすると、同時に CLTもインストールされるそうです。

command line tools インストール

xcodeをインストールせずに、CTLだけをインストールする場合は、

$ xcode-select --install

コマンドラインからできます。(やってみたら、30分ほどで完了。)

homebrew アップデート

これは前にインストールしたので、アップデートしました。

インストールは

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

アップデートするために brew updateとすると

Error: 
  homebrew-core is a shallow clone.
  homebrew-cask is a shallow clone.
To `brew update`, first run:
  git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
  git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow

... We don't do this for you
automatically to avoid repeatedly performing an expensive unshallow operation in
CI systems (which should instead be fixed to not use shallow clones). Sorry for
the inconvenience!

とエラーが出ましたが、

$ git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
$ git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow
$ brew update

で無事にアップデートできました。

tree コマンドのインストール

treeコマンドがインストールできることを下記のように確認しました。

$ brew install tree

$ which tree
/usr/local/bin/tree

これで、macOSに用意されていないLinuxのコマンドやツールがあっても、インストールできそうです。

転職して半年、材料科学分野でのデータ分析に従事

今の職場での仕事をこなしたり学んだりするのに忙しすぎて、最近、なぜ転職したのかを忘れかけています。しかし、なぜ職場を移ったのかは、今の職場でこれからどうするかを考えるために重要なことです。なので、忘れないうちに、書いておきます。

なぜ前の職場を出ようと思ったか

フォートランプログラムのチューニングという仕事を辞めて、別の新しい仕事を始めたかったからです。ただ、計算科学シミュレーションや、前の勤務先、前の勤務先での他の仕事のどれについても悪く言うつもりはありません。

私が辞めたかったのは、チューニングの大半を占める 単純作業で、コンパイルオプションをただ変えるだけという退屈きわまりない繰り返しでした。 そして、新しい仕事を始めたくなったのは、転職前の数年間、フォートランの部署に籍を残したままで、機械学習ソフト開発の部署で仕事をさせてもらっていたからです。機械学習ソフトの開発が自分の趣味嗜好に合致していると感じたとき、決心しました。C++Python が刺激的であることに比べて、フォートランが古臭いということも、決心を後押ししてくれました。

他方で、機械学習の仕事をするようになってからも、フォートランの部署に所属したままだったので、いつかはフォートランの仕事に戻ることになると分かっていました。なので、それを避けるために、社内転職活動をするようになりました。

しかし、社内転職できないまま、フォートランの世界に戻されることが確定しました。そこで、その日から、社外への転職活動を始めました。

どんな職場に転職しようとしたか

転職先としては、学生時代からの計算科学のバックグラウンドと、最近の機械学習ソフト開発の経験の両方が活かせるところを、探すことにしました。

しかし、そんな職場はニッチ過ぎるとも思っていました。そこで、都合よくニッチな希望がかなうよりも前に、機械学習ソフト開発の経験を評価してくれる職場か、あるいは、データ分析ができる職場から内定が得られれば、そこに転職しようとも決めていました。

ところが、転職活動は私が思っていたより厳しいものでした。いや、私の年齢からすると厳しいのが当然でした。そして、転職活動の方針を考え直したほうが良いのだろうかと思い始めたときに、今の勤務先からの内定と、別のデータ分析に関連する会社からの内定、また、別の機械学習ソフト開発の会社から最終面接に進めるという知らせが立て続けに来ました。

こうして私は転職活動を終えました。

今の職場で何を目指すか

今は、計算科学シミュレーションや実験の結果を、機械学習で分析しています。バズワードで言えば、マテリアルズ・インフォマティクスの仕事です。しかし、バズワードと現実は違います。転職してから半年が過ぎましたが、マテリアルズ・インフォマティクスとして喧伝されるほどの大きなデータセットを、私はまだ、分析したことがありません。

このデータサイズの小ささについて、 マテリアルズ・インフォマティクスビッグデータでなくスモールデータを扱う分野なのだ、という人もいます。しかし、私はそうは思いません。まだ、シミュレーションや実験によるデータの収集が進んでいないからだと思っています。

なので、実験結果のビッグデータを扱えるように、また、計算科学シミュレーションでデータを効率的に収集できるように、職場の計算インフラの整備を進めています。この整備には、前の勤務先で習得したスキルが役立っています。

こうして、計算科学のバックグラウンドを活かし、機械学習で分析をして、計算機インフラの整備をしているので、転職前の希望に近いところに来れたかもしれません。しかし、悩みもあります。それは、自分の専門として、計算科学シミュレーション、機械学習、ソフト開発のどこにも集中特化しておらず、力が分散してしまっているという悩みです。

私は、数理的手法を使いやすくするためのソフト開発をしたいので、マテリアルズ・インフォマティクスを使いやすくするためのソフトウェア・プラットフォーム開発に集中したいと思っています。しかし、所属部署が安定して利益を出せるようになるまでは、シミュレーションで分析する仕事をせずに、プラットフォームを作る仕事ばかりをしているわけにはいきません。かといって、専門を絞らずにあれもこれもという状態では、生産性を上げるのが難しいのです。

あるいは、単にいろいろと勉強不足なのかもしれません。それにしても、どうしたものか。。

macOS で .gpg ファイルを emacs から復号・編集・暗号化するために

Ubuntu で作った gpg ファイルを、macOSでも操作するために、必要なソフトをインストールして、設定しました。 (何をしたのか忘れかけているので、メモとして書いておきます。)

macOSバージョン

  • Mojave バージョン 10.14.6

Homebrew のインストール

参考:Qiita: macOSにHomebrewをインストール

$ /usr/bin/ruby -e \
"$(curl -fsSL \
https://raw.githubusercontent.com/Homebrew/install/master/install)"

emacs のインストール

参考:Qiita: homebrewからインストールできるemacsの違い

私は、ターミナルでemacsと打ったときには別ウィンドウでemacsが開いてほしいので、cask版emacsをインストールしました。

brew cask install emacs

gpg のインストール

参考: OS X の Emacs で EasyPG が gpg2 で Opening input file: Decryption failed, になったので対処した

他に以下をインストールしました。

  • gnupg: stable 2.2.17
  • pinentry: stable 1.1.0
  • pinentry-mac: stable 0.9.4

設定

emacs で、gpg ファイルを復号化して編集できるようになるまで、試行錯誤が必要でした。

参考: Login Register gpg 2.2 and epa

$ cat ~/.gnupg/gpg.conf 
ignore-mdc-error

参考: OS X の Emacs で EasyPG が gpg2 で Opening input file: Decryption failed, になったので対処した

~/.gnupg/gpg-agent.conf を作成して pinentry-program /usr/local/bin/pinentry-mac という設定を入れたところ、 Emacs 上でも *.gpg ファイルを開くときに pinentry-macパスフレーズをきかれるようになって、開けるようになりました。

$ cat .gnupg/gpg-agent.conf
# allow-emacs-pinentry
pinentry-program /usr/local/bin/pinentry-mac

注意すること

.gpg ファイルを編集・暗号化すると、そのパスフレーズは gpg-agent にキャッシュされる

なので、そのパスフレーズ で、.gpg ファイルが復号できるかを確認するには、パスフレーズを入力したターミナルとは、別のターミナルから、emacs を立ち上げる必要があります。

そこで、gpg-agent を一旦、止めて、再起動してから、.gpg ファイルが復号できるかを確認しています。(もっとスマートな方法を探していますが、わからないので。)

$ gpg-connect-agent killagent /bye
OK closing connection

$ gpg-connect-agent /bye
gpg-connect-agent: gpg-agentが実行されていません - '/usr/local/Cellar/gnupg/2.2.17/bin/gpg-agent'を開始します
gpg-connect-agent: agent の起動のため、5秒待ちます...
gpg-connect-agent: agent への接続が確立しました。

こうしないと、キャッシュされたパスフレーズemacsはその.gpgファイルを復号化してしまいます。

iCloud のDocumentsフォルダに、change directory するには

MacBook Air の使い方がまだわかっていないのかもしれませんが、 デフォルトでファイルは iCloud に保存するようになっているようです。

参考: ターミナルからiCloud driveに移動する方法

$ cd /Users/${USER}/Library/Mobile\ Documents/com~apple~CloudDocs/Documents

Docker で TensorFlow を Ubuntu 16.04 にインストール

職場では Anaconda で TensorFlow をインストール^1 したのですが、自宅では Docker でやってみました^2 ^3。やってみるまで、Anaconda, Docker の何が良くて、どのように使い分けるのか良く分かっていませんでした。なので実践から。

自宅PCはグラフィックボード AMD Radeon HD 7770 を積んでいて、SC15でRadeonでCUDAを使えるようにするよと発表^7 ^8があったと聞いているのですが、まずは、GPUなしでと、CPU版をインストールしました。

Dockerの入門的知識は必要

いきなり、Docker をインストールして、TensorFlowコンテナを実行してみると、いろいろとおかしなことが起きました。

やはり、最低限の知識として、Docker のイメージ・コンテナ管理の基本と、イメージのビルド方法くらいは必要です。今思うと、

Docker入門 – コンテナ型の仮想化技術の解説 ^4

の Quick Start -> Try it! と、

「さわって理解するDocker入門」オージス総研 大西 洋平 ^5

の第1回、第2回くらい、あるいは、

@IT > いまさら聞けないDocker入門 ^6

の第1-3回くらいを、読んでから取り掛かったほうが、早く出来たのかもしれません。

Docker をインストール

まず、必要なパッケージをインストールしました。

$ sudo apt-get update
$ sudo apt-get install -y --no-install-recommends \
    linux-image-extra-$(uname -r) \
    linux-image-extra-virtual
$ sudo apt-get -y --no-install-recommends install curl \
    apt-transport-https \
    ca-certificates \
    software-properties-common

次は、レポジトリをセットアップ。まずはDockerのオフィシャルGPG keyを追加しました。

$ curl -fsSL https://apt.dockerproject.org/gpg | sudo apt-key add -
OK

Key IDの検証。

$ apt-key fingerprint 58118E89F3A912897C070ADBF76221572C52609D
pub   4096R/2C52609D 2015-07-14
      フィンガー・プリント = 5811 8E89 F3A9 1289 7C07  0ADB F762 2157 2C52 609D
uid                  Docker Release Tool (releasedocker) <docker@docker.com>

安定版のレポジトリをセットアップ。

$ sudo add-apt-repository \
       "deb https://apt.dockerproject.org/repo/ \
       ubuntu-$(lsb_release -cs) \
       main"

これで、Dockerをインストールできるようになりました。あとは、

$ sudo apt-get -y install docker-engine

で docker-engine_17.04.0~ce-0~ubuntu-xenial_amd64.deb が入りました。

しかし、このままでは Docker を実行するためのスーパーユーザー権限が必要なので、、Ask ubuntu: problem with docker

After installing Docker you are prompted to add your user to the docker group. Simply run the command shown:

sudo usermod -aG docker $USER
You will need to close your session and log in again to have the change take effect.

にしたがって、sudo usermod -aG docker $USER を実行して、ログアウトして、ログインしました。すると、

$ docker version
Client:
 Version:      17.04.0-ce
 API version:  1.28
 Go version:   go1.7.5
 Git commit:   4845c56
 Built:        Mon Apr  3 18:07:42 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.04.0-ce
 API version:  1.28 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   4845c56
 Built:        Mon Apr  3 18:07:42 2017
 OS/Arch:      linux/amd64
 Experimental: false

のように問題なく version コマンドを実行できました。

TensorFlowコンテナを生成・実行

CPU安定版のDocker イメージからコンテナを生成させて、実行しました。

$ docker run -it -p 8888:8888 tensorflow/tensorflow
Unable to find image 'tensorflow/tensorflow:latest' locally
latest: Pulling from tensorflow/tensorflow
   ;

    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://localhost:8888/?token=(毎回、生成されるトークン)

で、最後に表示された「http://localhost:8888/?token=(毎回、生成されるトークン)」にブラウザでアクセスしてみました。

すると、図1のようにJupyter notebook が使えるようになりました。

図1: Jupyter notebook の画面(「TensorFlowが動作するDockerの開発環境を構築する」 ^3からの引用)

ただ、1_hello_tensorflow.ipynb を開いてみると、

Notebook validation failed

An invalid notebook may not function properly. The validation error was:
Notebook validation failed: Additional properties are not allowed (u'metadata' was unexpected):
{
 "output_type": "stream", 
 "text": "result:  [ 3.  3.  3.  3.]\n", 
 "name": "stdout", 
 "metadata": {}
}

というダイアログボックスがポップアップしました。何なのだ?

ともあれ、File -> New Notebook (python 2) で、 サンプルスクリプト

import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print(sess.run(hello))
a = tf.constant(10)
b = tf.constant(32)
print(sess.run(a+b))

を実行すると、

Hello, TensorFlow!
42

と結果が返ってきました。

ファイル名を sample.ipynb として、 File -> Save and Checkpoint として、ブラウザのタブを閉じて、再び、sample.ipynb を開いてみました。

こんどは、妙なダイアログボックスはポップアップしませんでした。 他のファイル、2_getting_started.ipynb 、 3_mnist_from_scratch.ipynb でも妙なダイアログボックスはポップアップしませんでした。ただ、1_hello_tensorflow.ipynb を開いてみると、今度も妙なダイアログボックスが。

よくわかりませんが、1_hello_tensorflow.ipynb だけのことなので、次に進みます。

Docker コンテナの停止と再スタート

Dockerコンテナを実行したターミナルで、Ctrl+C で、プロセスを止めました。

ps -a コマンドで、コンテナIDを調べて、startコマンドで再スタートさせました。(再スタートのコマンド名は start 、まぎらわしい。。)

$ docker ps -a
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS                     PORTS               NAMES
6a5ed12e18e1        tensorflow/tensorflow   "/run_jupyter.sh -..."   12 minutes ago      Exited (0) 5 minutes ago                       hardcore_goldwasser
$ docker start -i 6a5ed12e18e1

    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://localhost:8888/?token=(毎回、生成されるトークン)

http://localhost:8888/?token=(毎回、生成されるトークン)」にアクセスしてみると、 sample.py が前に保存にしたとおりの内容で残っていました。

Dockerイメージ作成

このコンテナを再びCtrl+Cで止めて、新しいDocker イメージをtfplussampleという名前で作ってみました。

$ docker commit 6a5ed12e18e1 tfplussample
sha256:07bddf474593056dee6a4162e67b89fde1015841327af8ff8dee565bb8d21fac
$ docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
tfplussample            latest              07bddf474593        10 seconds ago      1.13GB
tensorflow/tensorflow   latest              04f0b1131389        12 days ago         1.13GB

このDocker イメージからコンテナが生成され、実行できることは、

$ docker run -it -p 8888:8888 tfplussample

で確認しました。ここで、前に作った sample.ipynb を sample.py としてホストマシンにダウンロードしました。

Docker イメージをビルド

次のようなDockerfile

FROM tfplussample
COPY ./sample.py /tmp/sample.py

を作成して、 Dockerイメージをビルドしてみました。一行目は、新イメージのベースとなるコンテナ名、二行は、ホストマシンから新イメージのコンテナへのファイルコピーを指定しています。

-tオプションで、イメージ名 tfplussample2 タグ名 tag1 としました。

$ docker build -t tfplussample2:tag1  .Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM tfplussample
 ---> 07bddf474593
Step 2/2 : COPY ./sample.py /tmp/sample.py
 ---> 9de94c7d2502
Removing intermediate container 21067f8210cb
Successfully built 9de94c7d2502

Docker イメージを実行してみると、

$ docker run --rm -it tfplussample2:tag1 python /tmp/sample.py
Hello, TensorFlow!
42

のように、コンテナ内の/tmp/sample.py が実行されました。

まとめ

たしかに、インストールは簡単でした。TensorFlowに関係するファイルがDockerコンテナのなかにまとめられて、ホストマシンのほかのアプリから切り離されているようです。こうなると、他の機械学習関係のアプリやツールを別のコンテナに隔離することで、ライブラリバージョンの衝突などを回避できます。Pythonのバージョンの違いに悩まなくとも良くなるので、これは便利です。

それと、他人の作ったDockerイメージから、コンテナを簡単に自分のマシンに生成できるので、素早くアプリやツールに特化した実行環境を作れるようになります。これも便利です。一方で、Anaconda でも異なるpythonのバージョンを、別の環境に隔離できるのですが、環境を作るのは手作業なので時間がかかります。

ただ、Dockerの使い方を学ぶのに時間がかかりました。私の場合、半日。


参考

^1:Installing TensorFlow on Ubuntu : Installing with Anaconda

^2:Installing TensorFlow on Ubuntu : Installing with Docker

^3:TensorFlowが動作するDockerの開発環境を構築する

^4:Docker入門 – コンテナ型の仮想化技術の解説

^5:「さわって理解するDocker入門」オージス総研 大西 洋平

^6:@IT > いまさら聞けないDocker入門

^7:AMD Launches ‘Boltzmann Initiative’ to Dramatically Reduce Barriers to GPU Computing on AMD FirePro™ Graphics

^8:CUDAをRadeonで動かす(導入編)

メモ:Ubuntu 16.04 を 休止(ハイバネート)させるために (追記:休止できなくなることも)

Ubuntu 16.04 をインストールしただけでは、休止機能を使えませんでした。しかし、作業の途中で電源を落とすために必要なので、なんとか有効にしました。その方法をメモしておきます。

サスペンドできるようにした

インストール直後は、

$ sudo pm-hibernate

としても何も起こりませんでした。 また、もうひとつのコマンドでは、

$ sudo systemctl hibernate
Failed to hibernate system via logind: Sleep verb not supported

とエラーが出ました。

そこで、Ask ubuntu: How can I hibernate on Ubuntu 16.04? ^1

Secure Boot … It turns out that secure boot was the culprit: installing 16.04 you are asked what you want to do with it (which is a new thing as far as I can recall) and I kept it ON without giving it much thought.

After reboot and disabling secure boot in the BIOS settings (these are machine-specific, but usually pretty straightforward) … And indeed calling systemctl hibernate results in a successful hibernate/thaw sequence.

Moreover, after that I could see hibernation available as an option in various places of the graphical interface, without the need of any polkit hack. So it seems that systemd was actually guessing from /sys/power/disk that the system was not able to hibernate.

にしたがって、BIOSメニューから「安全なブートの構成」を見つけて、

安全なブート : 無効

にしました。すると、たしかに、ファイル/sys/power/disk は、

[disabled]

から、

[platform] shutdown reboot suspend

へと書き換えられました。しかし、私の場合、メニューに現れたのは、「ハイバーネート」ではなく、「サスペンド」でした。

そして、メニューのサスペンドを選ぶと、スクリーンはブラックアウトして、電源LEDの色が変わって、サスペンドしました。

そして、

$ sudo pm-hibernate

で、スクリーンはブラックアウトしましたが、電源はオンのままでした。それで、仕方なく、電源ボタン長押しで、強制的に電源を切らざるをえませんでした。

メニューに「ハイバネート」、しかし、電源はオンのまま

Ask ubuntu: Ubuntu 16.04 doesn’t hibernate ^2

You can also enable the hibernate option in the user menus. To do that, use your favorite text editor to create /etc/polkit-1/localauthority/50-local.d/com.ubuntu.enable-hibernate.pkla. Add the following to the file and save:

[Re-enable hibernate by default in upower]
Identity=unix-user:*
Action=org.freedesktop.upower.hibernate
ResultActive=yes

[Re-enable hibernate by default in logind]
Identity=unix-user:*
Action=org.freedesktop.login1.hibernate;org.freedesktop.login1.handle-hibernate-key;org.freedesktop.login1;org.freedesktop.login1.hibernate-multiple-sessions;org.freedesktop.login1.hibernate-ignore-inhibit
ResultActive=yes

そのとおりにやってみると、たしかに、メニューに「ハイバーネート」が現れました。しかし、クリックしても、休止せず、電源はオンのままでした。

休止できるようになった

次は、

Ask ubuntu: Ubuntu 16.04 doesn’t hibernate ^2

Since you’re running Ubuntu 16.04, you should consider running the native systemd suspend/hibernate services in lieu of the pm-utils tools.

In my own case, here’s what I’ve done to configure my machine for hibernate/resume using systemd:

にそって、まず、スワップ領域のUUID を、

tail -n -9 /proc/swaps | cut -d ' ' -f 1 | xargs sudo blkid

のように調べました^3

1) /etc/default/grub の GRUB_CMDLINE_LINUX_DEFAULT の行を、

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash pci=nomsi  resume=UUID=(上記で調べたUUID)"

のように書き換えました。

2) sudo update-grub

3) /etc/initramfs-tools/conf.d/resume に UUIDが正しく書き込まれていることを確認しました。

4) sudo update-initramfs -u

5) sudo service systemd-logind restart

6) 再起動。

これで、メニューの「ハイバーネート」で、電源がオフになり、電源をオンにすると、Ubuntu の認証画面が現れ、ログインすると、作業途中のデスクトップに戻れました。

これで、私自身もハイバーネートします。おやすみなさい。

追記

2017/05/05

使っているうちに、休止できなくなることが判明しました。休止できるのは、上記ステップ 2) , 4), 5) を繰り返して、再起動して、しばらくの間だけでした。それ以外のときは、メニューの「ハイバーネート」を選んでも、あるいは、 sudo pm-hibernate としても、画面表示は消えるものの、電源はオフにならず、オンのままでした。

また、sudo pm-hibernate を実行する前に、上記ステップ 2) , 4), 5) をしてみたのですが、それでも、画面表示は消えるものの、電源はオンのままでした。


参考

^1:Ask ubuntu: How can I hibernate on Ubuntu 16.04?

^2:Ask ubuntu: Ubuntu 16.04 doesn’t hibernate

^3:Ask ubuntu: Why isn’t Hibernate in Ubuntu 16.04 working and how to fix it?

Ubuntu 16.04 のインストールディスクは ネットワークアダプター Atheros AR8161 Gigabit Ethernet への対応が不完全だった

先代のメインPC^1機械学習の練習マシンとすべく、日本語版Ubuntu 16.04 をインストールしました。しかし、どういうわけかネットワーク接続が不安定で、数秒間つながって、切れて、また、つながって切れて、を繰り返していました。

しかも、「インストール中にアップデート」を選んだのに、まったくアップデートされていませんでした。

解決策

まず、件のPCでLANアダプタは

$ lspci | egrep '(Ethernet|Network)'
03:00.0 Ethernet controller: Qualcomm Atheros AR8161 Gigabit Ethernet (rev 08)

ということで、ググッてみました。

すると、[ubuntu] Ethernat / Wired connection not working^2

First, open Network Manager and set the MTU for the wired connection to 8192. Reboot and see if it works correctly

というアドバイスが。

再インストールと結果

そこで、Ubuntuインストールディスク起動後に、"Try ubuntu"を選んで、

$ sudo ifconfig eno1 mtu 8192

としてみると^3、安定してネットにつながるように。感動。 あとは、"Install Ubuntu"アイコンをクリック、今度はネットワークにつながるからなのか、前よりも早くインストールできました。

ただ、不思議なのは、そうしてインストールしたUbuntu 16.04 では、mtuの値を大きくしなくとも、安定してネットワークにつながっていることです。

$ sudo ip addr
   ;
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
   ;

ネットワーク接続 -> 有線接続1 -> Ethernet で見ても、

MTU 自動

となっています。

なぜなのか。。

まあ、これでネットから機械学習関連ツールをインストールできるようなったので、よしとします。まずは、TensorFlowのMNISTチュートリアルを理解するところからはじめます^4


参考

^1:「メモ:VMwareとVirtualBoxの仮想マシンを引っ越し」で書いたように、年末にブルースクリーンを頻発していた先代のメインPCが、最近はいたって好調なのです。

^2:[ubuntu] Ethernat / Wired connection not working

^3:Ubuntu 12.04:MTU値を変更しNetworkを最適化する

^4:「TensorFlowで学ぶディープラーニング入門 ~畳み込みニューラルネットワーク徹底解説」中井 悦司 2016/9/27