未変更のファイルが変更扱いになっていた問題(サブモジュール編)
最近、git add
してもgit checkout
しても、変更扱いされているファイル(以下hoge)がありました。
僕としてはhogeをまったく変更した記憶がないんですが・・
同じような現象としてファイルモードの問題があったので、
下記URLを参考に解決しようと思ったのですが、
あんまり関係ありませんでした(ノ゚゚Д゚゚)ノオラァッ!!
その後・・
たまたまgit submodule init
やgit submodule update
したときにhogeに対して下記エラーが発生しました。
No submodule mapping found in .gitmodules for path hoge
なんかサブモジュールになってる・・
工エエェェ(´д`)ェェエエ工
どうやら「インデックスに紐付いていないサブモジュールがあるぞい」というエラーらしいです。
サブモジュールはファイルモードが160000になっているため、
以下コマンドでインデックス一覧を確認できます。
git ls-files --stage | grep 160000
インデックス一覧と".gitmodules"ファイルを比べたときに一覧にしかないインデックスがあったので、git rm
することで無事に解決しました。
--cached
オプションを付けなければファイルごとサヨナラします。注意しましょう。
git rm --cached hoge
サブモジュールェ・・
追記
実はhogeは拾ってきたZshのプラグインで、こいつがコミット時にディレクトリエントリとみなされたことが原因でした。
git clone
したものをリポジトリに含むときにはちゃんとサブモジュールにしましょう。
参考URL
Macでトラックパッドのスピードを限界突破したい
最近全然更新してなかった割にはしょぼい記事ですが・・
Macのトラックパッドのスピードが遅いです。
Better Touch Toolを使って速くしているつもりですが、それでも遅いです。
すごいイライラします´д` ;
そこで、defaults
コマンドを使ってみました。
こいつはシステムやアプリの設定値を読み書きできるツワモノです。
$ defaults read -g com.apple.trackpad.scaling 8
現在、BTTで設定できる最大値の8になっているのですが、
あまりにも遅いので倍の16にしました!!
$ defaults write -g com.apple.trackpad.scaling 16
再起動後、めちゃくちゃ速くなりました。
しかし、BTTが勝手に設定値を書き換えるので併用できない・・
でも、BTTが使えないのは困る´д` ;
結局いい解決案は思いつかなかったんですが、defaultsコマンドが便利でいろいろできるので紹介させていただきました。
(この前までBTTで8以上に設定できたような気がするんだがなぁ・・)
BTTを使っていない人はこの手を使ってください。
でも、使ってない人はさっさと入れたほうがいいと思います_φ( ̄ー ̄ )カリカリ
参考URL
Magic trackpad tracking speed changes | Apple Support Communities
ScalaのArrayとApplyについて調べた
初、Scalaの記事です。
Scalaは言語仕様にオマジナイ的なものが少なくて、
勉強していて「なるほど、ここはこうなってんだ〜〜」て思うことが多いです。
さて、そんなScalaの配列ですが、定義方法だけでも結構あります。
val num: Array[Int] = new Array[Int](5); // 型と要素数で定義 val num = new Array[Int](5); // 型推論 val num: Array[Int] = new Array(5); // 型推論 val num = new Array(5); // Array[Nothing] val num: Array[Int] = new Array[Double](5); // error: type mismatch;
上記はコンストラクタを用いた初期化です。
型と要素数をきっちり定義してもよし、型推論に身を任せてもよしです。
ちなみにブラケットはジェネリックです。
C#あがりの自分にとってはなつかしいものです(-_- )シミジミ
またクラスやオブジェクトにはApplyメソッドという特別なメソッドを定義することができ、定義されていればクラス名(オブジェクト名)のみで呼び出せます。
ArrayオブジェクトではArrayクラスのコンストラクタを呼び出すように実装されているので、 インスタンスの生成は以下のように記述することもできます。
val num: Array[Int] = Array[Int](1, 2, 3, 4, 5); // 型と初期値で定義 val num = Array[Int](1, 2, 3, 4, 5); // 型推論 val num: Array[Int] = Array(1, 2, 3, 4, 5); // 型推論 val num = Array(1, 2, 3, 4, 5); // Array[Int] val num: Array[Int] = Array[Double](1, 2, 3, 4, 5); // error: type mismatch
Applyメソッドあなどれん・・
こんなかんじでオブジェクトをファクトリーにして同名クラスのインスタンスを生成させていることが多いです。
ちなみに、オブジェクト名とクラス名が同じものをコンパニオンオブジェクトといいます。
また、Applyクラスでは要素の取得・代入するように実装されているので、 要素の取得・代入は以下のように記述することができます。
val num = Array(1, 2, 3, 4, 5); num(0) // 1 num.apply(0) // 1 num // 1, 2, 3, 4, 5 num(0) = 6 num.update(1, 7) num // 6, 7, 3, 4, 5
引数がふたつのときはUpdateメソッドを呼び出すように実装されています(こっちはオーバーロード)
うーん、Scalaはおもしろいですねー^_^
補足
実際のコードはこんなかんじです。
Arrayオブジェクト
def apply[A: ClassManifest](xs: A*): Array[A] = { val array = new Array[A](xs.length) var i = 0 for (x <- xs.iterator) { array(i) = x; i += 1 } array }
CentOS 6.4にTorch7をインストールしてみた
最近あまり記事書いてないなーと思いながら投稿・・
巷で噂のディープラーニングをやろうと思ってTorch7をインストールしてみました。
CentOS 6.4でやりました。
ディープラーニング系のライブラリは導入が割とメンドクサいらしく日本語の記事が少ないですね。
H2OとかCaffeとかいろいろあるのですが、
H2OはR言語なのがなんとなく嫌で、Caffeは導入で死ぬことが多いっぽかったのでTorch7でいっかーくらいの気持ちでTorch7にしました。
こちらに導入手順があるのですが、僕のCentOS 6.4だと依存ライブラリ解決スクリプトが、
/etc/os-release
ファイルがないという理由でちゃんと動かなかったので、
依存ライブラリの一覧だけ引っ張ってきて、普通にyum
コマンド叩いてインストールしました。
sudo yum install -y cmake curl readline-devel ncurses-devel \ gcc-c++ gcc-gfortran git gnuplot unzip \ nodejs npm libjpeg-turbo-devel libpng-devel \ ImageMagick GraphicsMagick-devel fftw-devel \ sox-devel sox SDL2-devel zeromq3-devel \ qt-devel qtwebkit-devel sox-plugins-freeworld
あと、OpenBlasとかいうライブラリも必要っぽかったので入れました。
これに関してもスクリプトから引っ張ってきただけです。
cd /tmp/ git clone https://github.com/xianyi/OpenBLAS.git cd OpenBLAS if [ $(getconf _NPROCESSORS_ONLN) = 1 ]; then make NO_AFFINITY=1 USE_OPENMP=0 USE_THREAD=0 else make NO_AFFINITY=1 USE_OPENMP=1 fi RET=$?;_ if [ $RET -ne 0 ]; then echo "Error. OpenBLAS could not be compiled"; exit $RET; fi sudo make install RET=$?;_ if [ $RET -ne 0 ]; then echo "Error. OpenBLAS could not be installed"; exit $RET; fi
最後にPythonとipythonを入れたら依存関係は完了です(ipythonのバージョンが古いとダメみたいです)
git clone https://github.com/torch/distro.git ~/torch --recursive cd ~/torch; ./install.sh
後は上記コマンドを実行して、シェルスクリプトを再読み込みしたらいけました。
vagrant:^_^[~]$ th ______ __ | Torch7 /_ __/__ ________/ / | Scientific computing for Lua. / / / _ \/ __/ __/ _ \ | Type ? for help /_/ \___/_/ \__/_//_/ | https://github.com/torch | http://torch.ch th>
う~ん、なんかざっくりですがインストールできました。
近々、社内の勉強会でディープラーニングの発表をしないといけないのでさわっていこうと思います。
追記
あとから確認したんですが、SDL2-develとsox-plugins-freeworldがインストールできていなかった・・
どちらもサウンド系のライブラリみたいなんですが、音声解析とかさせるときに使うのかな??
入れる場合はソースから入れる必要があるかもしれません。
DBIxでN+1問題に直面した・・其の壱
いにしえのコードを修正していたらDBIxでN+1問題に直面している部分を発見した!!
なので解決策をサクッと書こうと思います(/・ω・)/
初めにN+1問題とは
PerlのDBIxのようなORMは最適化のために余分なカラムは読み込まないようになっていることが多いです。
そのため、読み込まれていないカラムを表示しようとすると、
本来のSQL(1)に加えて、各レコードごとに1回のSQL(N)が実行されてしまいます/(^o^)\ナンテコッタイ
つまり、無駄にSQLが発行され、表示に時間がかかります。
Rubyあまり触ったことないんですが、参考にした記事がRubyなのでRubyにもいえる話なんでしょうね・・('A`)
たとえば以下のようなn_plus_one_problem
データベースがあって
author
テーブル
author_id | name |
---|---|
1 | hoge |
2 | huga |
book
テーブル
book_id | title | author_id |
---|---|---|
1 | aaaa | 1 |
2 | bbbb | 1 |
3 | cccc | 2 |
4 | dddd | 2 |
author
テーブルとbook
テーブルに1対多のリレーションが貼られているとします。
本の情報を表示したいとき、
Controller側は
sub index : Path :Args( 0 ) { my ( $self, $c ) = @_; my $book_rs = $c->model( 'Master::Book' ); $c->stash( book_rs => $book_rs ); return; }
View側は
<table border="1"> <tr> <th>Book ID</th> <th>Book Title</th> </tr> [% WHILE ( book = book_rs.next ) %] <tr> <td>[% book.book_id %]</td> <td>[% book.title %]</td> <tr> [% END %] </table>
とすればいいですね。
すると、クエリログはこうなります(DBIx::QueryLogモジュール)
[2015-06-13T06:57:56] [DBIx::Class::Storage::DBI] [0.000502] SELECT COUNT( * ) FROM book me JOIN author author ON author.author_id = me.author_id at.. [2015-06-13T06:57:56] [DBIx::Class::Storage::DBI] [0.000452] SELECT me.book_id, me.title, me.author_id FROM book me JOIN author author ON author.author_id = me.author_id at..
While文を回すためのカウントSQLは例外として、本体のSQLで1回のクエリが走っているのが分かります。
そこに著者の情報も表示したくなったとき、
Controller側は
sub index : Path :Args( 0 ) { my ( $self, $c ) = @_; my $book_rs = $c->model( 'Master::Book' )->search( undef, { join => 'author' } ); $c->stash( book_rs => $book_rs ); return; }
View側は
<table border="1"> <tr> <th>Book ID</th> <th>Book Title</th> <th>Author ID</th> <th>Author Name</th> </tr> [% WHILE ( book = book_rs.next ) %] <tr> <td>[% book.book_id %]</td> <td>[% book.title %]</td> <td>[% book.author.author_id %]</td> <td>[% book.author.name %]</td> <tr> [% END %] </table>
とすればいいですね。
すると、クエリログはこうなります。
[2015-06-13T07:00:28] [DBIx::Class::Storage::DBI] [0.000439] SELECT COUNT( * ) FROM book me JOIN author author ON author.author_id = me.author_id at.. [2015-06-13T07:00:28] [DBIx::Class::Storage::DBI] [0.000330] SELECT me.book_id, me.title, me.author_id FROM book me JOIN author author ON author.author_id = me.author_id at.. [2015-06-13T07:00:28] [DBIx::Class::Storage::DBI] [0.000434] SELECT me.author_id, me.name FROM author me WHERE ( me.author_id = '1' ) at.. [2015-06-13T07:00:28] [DBIx::Class::Storage::DBI] [0.000213] SELECT me.author_id, me.name FROM author me WHERE ( me.author_id = '1' ) at.. [2015-06-13T07:00:28] [DBIx::Class::Storage::DBI] [0.000601] SELECT me.author_id, me.name FROM author me WHERE ( me.author_id = '2' ) at.. [2015-06-13T07:00:28] [DBIx::Class::Storage::DBI] [0.000196] SELECT me.author_id, me.name FROM author me WHERE ( me.author_id = '2' ) at..
わ~~お!!なんかたくさん走ってますね!!
さらに、SELECT句をダンプするとこうなります。(Data::Printerモジュール)
select [ [0] "me.book_id", [1] "me.title", [2] "me.author_id" ]
JOINはしたものの結合先のテーブル情報はロードされていないことが分かります。
しかし、Viewでauthor
テーブルの情報を表示しようとしているため、
リレーションを便りにクエリが実行され、テーブル情報を取ってこようとします。
結果、N+1回クエリが実行されてしまいます。
少し古い情報ですが、Catalystのオレンジ本ではN+1問題を解決するために、別テーブルのカラムを参照する際にはJOINではなくPREFETCHを推奨しています。
実際、JOINではなくPREFETCHを用いてみると、
[2015-06-16T06:16:31] [DBIx::Class::Storage::DBI] [0.000633] SELECT COUNT( * ) FROM book me JOIN author author ON author.author_id = me.author_id at.. [2015-06-16T06:16:31] [DBIx::Class::Storage::DBI] [0.000285] SELECT me.book_id, me.title, me.author_id, author.author_id, author.name FROM book me JOIN author author ON author.author_id = me.author_id at..
なんかいけましたね(。-`ω´-)ンー.
select [ [0] "me.book_id", [1] "me.title", [2] "me.author_id", [3] "author.author_id", [4] "author.name" ]
このようにauthor
テーブルの情報がすでに読み込まれていることが分かります。
PREFETCHは結合したテーブルのカラムを自動的に読み込んでくれます。
デメリットとして無駄なデータの読み込みは発生しますが、このほうがミスは少なそうですね。
もしRubyのORMにPREFETCHに相当するものがあるのであれば、それを使えばいいかもしれません(調べてないけどねw)
しかし、DBIxのPREFETCHはクセの強いやつで、そういう訳にもいきません。
少なくとも僕の使ったバージョンでは・・
その辺の話は次回にさせていただく予定です(まとめるのつらい・・)
参考URL
スタブでオリジナルのメソッドを呼び出す
Test::Mock::Guardモジュール便利ですよね。シンプルで使いやすいので、よくこれでメソッドの動作を変えたりしてます。
しかしこの前、かなりシビアな条件でのみ起こり得るバグに遭遇してしまい、
Forkしたりスリープ埋め込んだりして、
なんとか再現しようとしたら見事に再帰りました(¨)( :)(..)(: )ゴ-ロゴロ
#!/usr/bin/env perl use strict; use warnings; use utf8; use Test::More; use Test::Mock::Guard 'mock_guard'; run_test() if $ENV{ HARNESS_ACTIVE }; { package Test; sub add { return $_[0] + $_[1]; } } sub run_test { my $guard = mock_guard( 'Test', +{ add => sub { print "hoge\n"; sleep 1; shift->add( 1, 2 ); } } ); # オリジナルのTest->addメソッドを期待していた is( Test->add( 1, 2 ), 3 ); done_testing; return; }
これを実行するとこうなる。
akata:^_^[~/perl_test/mock_test]$ prove -v main.pl main.pl .. hoge hoge . .
( ゚д゚)ポカーン
モックされたメソッドが永遠に呼び出され続けています。
仕方がないのでTest::MockModuleモジュールを使って、内部からオリジナルのメソッドを呼び出すことで解決出来ました。
sub run_test { my $module = Test::MockModule->new( 'Test' ); $module->mock( 'add', sub { shift; print "hoge\n"; sleep 1; $module->original( 'add' )->( @_ ) } ); is( Test->add( 1, 2 ), 3 ); done_testing; return; }
akata:^_^[~/perl_test/mock_test]$ prove -v main.pl main.pl .. hoge ok 1 1..1 ok All tests successful. Files=1, Tests=1, 2 wallclock secs ( 0.02 usr 0.00 sys + 0.03 cusr 0.00 csys = 0.05 CPU) Result: PASS
うーん。いけたけどこれしかないのかな(。-`ω´-)ウーム
ScalaをインストールするためのAnsible-Roleを書いた
ちゃんとgit pull
した後にpullされているか確認しましょう。
ひどい目にあいますよ\(^o^)/
はい、今回はScala(ついでにsbtも)です。結論:めっちゃ簡単だった
第1弾Git
: GitをインストールするためのAnsible-Roleを書いた - Akata Works第2弾Vim
: VimをインストールするためのAnsible-Roleを書いた - Akata Works第3弾Zsh
: ZshをインストールするためのAnsible-Roleを書いた - Akata Works
Yumリポジトリの追加をget_urlモジュールでやりました。
あと、yumモジュールにURLを指定するとrpmファイルをlocal installできます。
localhostオプションは非推奨らしいのでこっちを使いましょー!!
とまあ、このへんがポイントでしょうか??
短いからソースコードも貼っとこう(これで安心だ)
--- - name: Install dependent repositories get_url: url=https://bintray.com/sbt/rpm/rpm dest=/etc/yum.repos.d/bintray-sbt-rpm.repo mode=0644 - name: Install dependent libraries yum: name={{ item }} state=present with_items: - java7 - http://downloads.typesafe.com/scala/2.11.4/scala-2.11.4.rpm - sbt
local installだとyumモジュールの冪等性チェックに時間がかかるような気がします。
ダウンロードとインストールを分けたほうがいいかもしれませんね。
おまけ
git pull
されてなかったのはこれと同じっぽい
submoduleの闇にはまりつつあるな・・