SSブログ
プログラミング ブログトップ
前の10件 | -

mingw環境構築メモ [プログラミング]

 AperyがVisual Studioでビルドできないのでmingwを入れる必要があるが、ぐぐって一番上の方法を試すと失敗するのでメモ

■手順
 MSYS2をいれてPACMANでパッケージを追加する
 http://sourceforge.net/projects/msys2

 インストール後、「MinGw-w64 Win64 Shell」を実行する。
 「MSYS2 Shell」はMSYS2のDLL必須になってしまう。

$ update-core
$ pacman -Su

 コアコンポーネントのアップデートを行うとシェルの動作がおかしくなるので立ち上げ直したほうがよさそう

$ pacman -S base-devel
$ pacman -S msys2-devel
$ pacman -S mingw-w64-x86_64-toolchain

 これで大体入る。vim,gtags(global),gdbなどがインストールできる。
 デフォルトで色がつかないので.bashrc/.gitconfig/.vimrcなどは適宜更新する

■Aperyのビルド

$ git clone https://github.com/HiraokaTakuya/apery
$ cd apery/src
$ make bmi2

 makeだけだとデバッグビルドになる
 やり直すときはmake clean後に行う

■速度
 https://twitter.com/nodchip/status/642123872217665540
 配布版はPGOビルドされているので速い


gpsfishをstockfish 5ベースにしてみた [プログラミング]

Stockfishがコンピュータチェス大会?で優勝した記念で5としてリリースしたらしい

http://blog.stockfishchess.org/post/87376326602/stockfish-5

というわけで、さくっとマージしてみた

・gpsfish_dd_2ブランチを伸ばしている
・タグはまだうってない

dd -> 5 で結構積極的な探索最適化が入っていて、今からマージするなら5がいいんじゃないかと言ってみる。
ただ、2.1のほうが相変わらず強い。というか2.1のgpsfishoneビルドが驚異的な強さ。もしかするとgpsfishone用の何かが足りてないかもしれない。
また、一回盛大に大逆転負けしてたのを見てしまったので、何かあるかもしれない。

https://github.com/woodyring/Stockfish


茶柱 2.0 をso-netに導入する [プログラミング]

http://starknights.seesaa.net/article/395784000.html

これ

使い方というか、外部CSSでも置いててくれればいいのだが、内容なので自力でコピペする必要がある。

デザイン -> テンプレート管理 -> html編集 で編集する。
からの間にスタイルシートのタグを作成し、http://starknights.seesaa.net/styles-index.css の中にあるchagasiraあたりの部分をまるっとコピペする

<style type="text/css">
ここにコピペ
<style>


そうすると<span class="chabasira"></span>で茶柱、<span class="chabasira is-set"></span>で緑柱が使える。













茶柱テスト緑柱テスト

Ubuntu server で日本語の文字化け [プログラミング]

注意点:動いてからまとめたので何が原因かは不明

余計なものを入れたくないのでServerをインストールしたのだが、デフォルトがLANG=Cなので日本語は当然化けたりする。

でもUTF-8なら別に読めるだろ・・・と思ってたら見事に間違いだった。
oslはなぜかコメントが日本語なので改行がひどいことになってて苦労した。

localeの確認はlocale -a

$ locale -a
C
C.UTF-8
POSIX
en_AG
en_AG.utf8
en_AU.utf8
en_BW.utf8
en_CA.utf8
en_DK.utf8
en_GB.utf8
en_HK.utf8
en_IE.utf8
en_IN
en_IN.utf8
en_NG
en_NG.utf8
en_NZ.utf8
en_PH.utf8
en_SG.utf8
en_US.utf8
en_ZA.utf8
en_ZM
en_ZM.utf8
en_ZW.utf8


でja_JP.UTF-8が無いので何かパッケージを入れたが、何だったか忘れた
すると、locale -aしたときにja_JP.utf8が出てきた。

これで大丈夫だろうと、日本語のファイルを開いてみるが、まだダメ

そもそも文字コードがUTF-8じゃないんじゃないかと思い、「nkf -g」で調べてみると無情の「UTF-8」

どうしたもんかと思ってたが、locale-genで良いらしい

http://dqn.sakusakutto.jp/2013/03/ubuntu_locale.html

sudo locale-gen ja_JP.UTF-8


これがキモだった模様。多分日本語Ubuntuだと勝手にやってくれてるんだろう。

gitのメモ [プログラミング]

毎回忘れるのでまたメモ

sudo apt-get install git-core

UbuntuではなぜかNanoだったので変更
日本語文字化け対策らしい
git config --global core.editor 'vim -c "set fenc=utf-8"'

ユーザー設定無しでコミットした場合に出るメッセージ

git config --global user.name なまえ
git config --global user.email メアド

コミットしなおしする場合
git commit --amend --reset-author

ブランチの移動
git tag
git checkout [tag名]

checkoutするとgit logで他のログが見えなくなるが水銀党の俺としては大変遺憾である。
が、でかいプロジェクトだとこうしないと余計なログみせられていみわからんみたいな感じだろうか
ここらへんは未だによくわからん

マージ方法
A-Bのようにブランチがあるとして

git checkout A
git commit -m A'
git checkout A <念のため
git checkout B
git merge A'

とすると、A'とBでマージされたものが、コミット直前の状態になる
コンフリクトした場合は例のわかりにくい <<<<や====や>>>>という差分が入ったソースが作成される。
これの解決をファイルを1つ1つ開いていちいちやる必要はない模様
http://qiita.com/yuya_presto/items/5d99499cf96c0ebb09f8

git mergetool

これで未解決のものはすべてvimdiffで開いてくれる。
でもWinMergeが一番使いやすい。vimdiffは色と操作性が合わない。

コンパイラによる3バイト配列同士の演算の最適化 [プログラミング]

(細かいのは後で書くか放置)

C++では参照を使うことでコピー用の一時オブジェクトが省略される場合があるというのは知っていた

そこで某bitboardのu32 p[3]な配列がoperator | で一時オブジェクト無しにアセンブラが吐出されるかを確認してみた

struct bitboard {
   unsigned int p[3];
};
inline bitboard operator | ( const bitboard &l, const bitboard &r ) 
{
    bitboard tmp;
    tmp.p[0] = l.p[0] | r.p[0];
    tmp.p[1] = l.p[1] | r.p[1];
    tmp.p[2] = l.p[2] | r.p[2];
}

bitboard b[3];
b[0] = b[1] | b[2];


みたいな感じで書いた時にどういうアセンブラが出るか

コンパイラはVisutalStudio2008を使った(古い)

当然Releaseビルドで、速度優先最適化をした後、アセンブリコードを吐き出させる

まずインラインによって、push/popがないのは確認した。ここは合格。

次にoperator | の展開だがb[1]とb[2]のpと思われる領域と
レジスタeax,ecx,edxを使用したmov と orが3個ずつ生成され、
ダイレクトにb[0]と思われる領域にmovしていた

mov eax, b[1].p[0]
mov ecx, b[1].p[1]
mov edx, b[1].p[2]
or    eax, b[2].p[0]
or    ecx, b[2].p[1]
or    edx, b[2].p[2]
mov b[1].p[0], eax
mov b[1].p[1], ecx
mov b[1].p[2], edx


3つの汎用データレジスタが一時オブジェクトの代わりになっていて無駄なコピーが発生していない
(ebxを使わないのはなにか歴史的な意味があるのだと思う)

次にコンパイルオプションで /arch:SSEとしても何も変わらなかった

さらに/arch:SSE2としたときに問題がおきた

コピーをmovq(quad word move)を使おうとするのだが、配列は3個しか無い
そこで、変な領域の値(Txxxxx)をコピーしてORした後もとに戻していた

<詳細は覚えていたら後で書く>

「コンパイラは8バイト単位でコピーしつつ、それによって上書きしてしまった領域をもとに戻そうとする」
というコードに変換してしまう

なので、SSE2最適化は8バイトでアライメントされていないとパフォーマンスが落ちる可能性が高い?
(速度的な検証はしていない)

また上記のpの配列を4つ(4*4=16バイト)にしても同じで、operator | が12バイトしか使わないコードであっても最後の4バイトを使うつもりがないとはコンパイラにはわからない

そこで、16バイト化+SSE4.1の128bitmove(movqなんとか)を使用するとわずか3命令で動作するのは確認できた

<これも後で書く>

というわけで、

・8バイト単位のアクセスになっている保証がない場合にはSSE2は使わないほうが良さそう
・なのでSSE4やAVXなどで自力で書けば紛れがないので書く価値はある

Intelコンパイラは持ってないのでわからん。
あとGCCやLLVMでも試してみたいところだが、環境が無い罠

GPSFISHのビルド [プログラミング]

2chを見てたら、なんでもGPSFISHがボナンザ有料版(6.1.1)に2勝8敗だったという。

で、ビルド方法を書いたサイトがあったので真似してやってみた。

http://www.geocities.jp/shogi_depot/doc/gpsfish_cygwin.htm

GPSFISHは元々Linuxのソフトウェアなので、Windowsでビルドするには骨が折れる。
が、そこはCygwinというLinux環境もどきを作ってくれるソフトウェアを使うことで対応している。

が、完全に互換というわけでもないので、いくつかは修正がいる。

で、基本的に上の通りにやればOKなのだが、いくつかハマりポイントというか、よく知らないとはまるポイントがあったのでまとめておこうと思う。

■ソースコードの取得

http://gps.tanaka.ecc.u-tokyo.ac.jp/gpsshogi/index.php?GPSFish

これは本家のところからダウンロードすればよいのだが、3つのリポジトリからダウンロードする必要がある。
SVN使うのがめんどくさいという人は、Tar.gz形式のアーカイブをダウンロードできるのでそれでダウンロードすれば良い。自分はそうした。

http://gps.tanaka.ecc.u-tokyo.ac.jp/cgi-bin/viewvc.cgi/trunk/osl/
http://gps.tanaka.ecc.u-tokyo.ac.jp/cgi-bin/viewvc.cgi/trunk/gpsshogi/?root=gpsshogi
http://gps.tanaka.ecc.u-tokyo.ac.jp/cgi-bin/viewvc.cgi/branches/gpsfish_dev/?root=gpsfish

全部落としてきて、並列に展開すれば良い。

■Cygwinで必要なもの

散発的に書かれていて、手順通りに進めるといちいちCygwinを起動しないといけなくなる
必要な物は

gcc,make,iconv-dev,libboost-dev,libbz2-dev

あたり。コンパイル時にヘッダファイルが必要な場合は-devなパッケージを選択するのが世の常。

■環境変数

OSL_HOMEをgpsshogiフォルダに設定

とあるが、すでにコンパイル済みGPSFISHをインストールしてある場合、別のフォルダになっていると思うのでそれを変更する必要がある。

■変更パッチ

文字で書かれているとよくわからないのでパッチ化。

diff -r 7c48bab4e7c3 gpsfish_dev/src/Makefile
--- a/gpsfish_dev/src/Makefile	Sat Jul 27 00:31:09 2013 +0900
+++ b/gpsfish_dev/src/Makefile	Sat Jul 27 18:17:23 2013 +0900
@@ -54,8 +54,15 @@
 
 programs : gpsfish
 
-gpsfish: $(OBJS) $(FILE_OSL_ALL)
-	$(CXX) -o $@ $(CXXFLAGS) $(PROFILE_USE) $(LDFLAGS) $(OBJS) $(FILE_OSL_ALL) $(LDLIBS) $(LOADLIBES) -lbz2
+gpsfish: $(OBJS)
+	$(CXX) -o $@ $(CXXFLAGS) $(PROFILE_USE) $(LDFLAGS) $(OBJS) \
+../../osl/release/libosl_search.a ../../osl/release/libosl_board.a \
+-lboost_filesystem-mt.dll -lboost_serialization-mt.dll -lboost_iostreams-mt.dll \
+-lboost_date_time-mt.dll -lboost_system-mt.dll -lboost_thread-mt.dll -lboost_program_options-mt.dll \
+-lpthread -lbz2 -liconv
+
+#gpsfish: $(OBJS) $(FILE_OSL_ALL)
+#	$(CXX) -o $@ $(CXXFLAGS) $(PROFILE_USE) $(LDFLAGS) $(OBJS) $(FILE_OSL_ALL) $(LDLIBS) $(LOADLIBES) -lbz2
 
 gpsfishoneprof: mainone.cc
 	$(CXX) -o $@ $(CXXFLAGS) $(OSL_HOME_FLAGS) $(PROFILE_GENERATE) $(LDFLAGS) $< $(LDLIBS) $(LOADLIBES) -lbz2
diff -r 7c48bab4e7c3 gpsfish_dev/src/search.cpp
--- a/gpsfish_dev/src/search.cpp	Sat Jul 27 00:31:09 2013 +0900
+++ b/gpsfish_dev/src/search.cpp	Sat Jul 27 18:17:23 2013 +0900
@@ -663,12 +663,14 @@
 
   // UCI protol is not clear on allowing sending an empty ponder move, instead
   // it is clear that ponder move is optional. So skip it if empty.
+#if 0
   if (ponderMove != MOVE_NONE)
 #ifdef GPSFISH
     cout << " ponder " << move_to_uci(ponderMove);
 #else
       cout << " ponder " << ponderMove;
 #endif
+#endif
 
   cout << endl;
 
diff -r 7c48bab4e7c3 gpsfish_dev/src/ucioption.cpp
--- a/gpsfish_dev/src/ucioption.cpp	Sat Jul 27 00:31:09 2013 +0900
+++ b/gpsfish_dev/src/ucioption.cpp	Sat Jul 27 18:17:23 2013 +0900
@@ -106,7 +106,7 @@
     mib[1] = HW_USERMEM;
     if (sysctl(mib, 2, &usermem, &len, NULL, 0) == 0
        && len == sizeof(usermem)) {
-      memory = std::min((size_t)2048, usermem/1024/1024/4);
+      memory = std::min((size_t)1024, usermem/1024/1024/4);
     }
   }
 #  elif defined (_WIN32)
@@ -115,7 +115,7 @@
     statex.dwLength = sizeof(statex);
     GlobalMemoryStatusEx(&statex);
     const size_t bytes = statex.ullTotalPhys; // in bytes
-    memory = std::min((size_t)2048, std::max(memory, bytes/1024/1024/4));
+    memory = std::min((size_t)1024, std::max(memory, bytes/1024/1024/4));
   }
 #  else
   {
@@ -124,7 +124,7 @@
     std::ifstream is("/proc/meminfo");
     if (is >> name >> value >> unit
        && name == "MemTotal:" && unit == "kB")
-      memory = std::min((size_t)2048, std::max(memory, value/1024/4));
+      memory = std::min((size_t)1024, std::max(memory, value/1024/4));
   }
 #  endif
   o["Hash"] = UCIOption(memory, 4, 8192);
@@ -145,7 +145,7 @@
   o["Emergency Base Time"] = UCIOption(200, 0, 30000);
   o["Emergency Move Time"] = UCIOption(70, 0, 5000);
 #endif
-  o["Minimum Thinking Time"] = UCIOption(20, 0, 5000);
+  o["Minimum Thinking Time"] = UCIOption(1500, 0, 50000);
 #ifndef GPSFISH
   o["UCI_Chess960"] = UCIOption(false);
   o["UCI_AnalyseMode"] = UCIOption(false);
diff -r 7c48bab4e7c3 osl/lib/misc/iconvConvert.cc
--- a/osl/lib/misc/iconvConvert.cc	Sat Jul 27 00:31:09 2013 +0900
+++ b/osl/lib/misc/iconvConvert.cc	Sat Jul 27 18:17:23 2013 +0900
@@ -73,7 +73,7 @@
   const char * inbuf = src.c_str();
   char outbuf[1024], *outbufptr = outbuf;
   size_t inbytesleft = src.size(), outbytesleft = 1024;
-#if (defined __linux__ || defined __APPLE__)
+#if (defined __linux__ || defined __APPLE__ || defined __CYGWIN__)
   typedef char ** iconv_inbuf_t;
 #else
   typedef const char ** iconv_inbuf_t;
diff -r 7c48bab4e7c3 osl/lib/misc/ncores.cc
--- a/osl/lib/misc/ncores.cc	Sat Jul 27 00:31:09 2013 +0900
+++ b/osl/lib/misc/ncores.cc	Sat Jul 27 18:17:23 2013 +0900
@@ -4,7 +4,7 @@
 #include 
 #include 
 
-#if defined(__linux)
+#if defined(__linux) || defined(__CYGWIN__)
 #   include 
 #elif defined(__APPLE__)
 #   include 
@@ -21,7 +21,7 @@
 ncores() {
   int cpuCount = 1;
 
-#if defined(__linux)
+#if defined(__linux) || defined(__CYGWIN__)
   cpuCount = sysconf(_SC_NPROCESSORS_ONLN);
 #elif defined(__APPLE__)
   kern_return_t kr;
diff -r 7c48bab4e7c3 osl/makefile.conf
--- a/osl/makefile.conf	Sat Jul 27 00:31:09 2013 +0900
+++ b/osl/makefile.conf	Sat Jul 27 18:17:23 2013 +0900
@@ -27,7 +27,7 @@
 USE_GCH ?= no
 USE_BOOST_POOL_ALLOCATOR ?= 0
 USE_TBB_SCALABLE_ALLOCATOR ?= 0
-USE_TCMALLOC ?= 1
+USE_TCMALLOC ?= 0
 TCMALLOC ?= google-perftools-1.7
 USE_TBB ?= 0
 GTEST ?= gtest-1.1.0


あとはmakeを4回ぐらいやればコンパイルできる。
ここらへんは本家と同じはず。

■Cygwin的な準備

Cygwin環境だとDLLのパスを通す的な何かがいる
やりかたをまとめたサイトの人のときよりboostのバージョンがあがっていたので以下の様な感じ。

-rw- 51214 2013-05-09 08:10 cygboost_date_time-mt-1_53.dll
-rw- 79374 2013-05-09 08:10 cygboost_filesystem-mt-1_53.dll
-rw- 87566 2013-05-09 08:10 cygboost_iostreams-mt-1_53.dll
-rw- 384014 2013-05-09 08:10 cygboost_program_options-mt-1_53.dll
-rw- 430606 2013-05-09 08:10 cygboost_serialization-mt-1_53.dll
-rw- 16398 2013-05-09 08:10 cygboost_system-mt-1_53.dll
-rw- 83982 2013-05-09 08:10 cygboost_thread-mt-1_53.dll
-rw- 62990 2011-05-22 04:17 cygbz2-1.dll
-rw- 105501 2013-06-16 13:23 cyggcc_s-1.dll
-rw- 899101 2013-06-16 13:45 cygstdc++-6.dll
-rw- 3113058 2013-07-23 00:07 cygwin1.dll
-rw- 74269 2013-05-10 06:21 cygz.dll
-rwx 10676626 2013-07-27 01:32 gpsfish.exe*

これだけあればgpsfishが動く。

gpsfishができたら動かしてusiとコマンドをうつと、何やらいろいろでてくればOK。
ここでクラッシュするようだと何か問題がある。

■コンパイルしてみてわかったこと

本題はここなんだが、明確な優位性はなかった。というか逆に弱くなってるんじゃとすら思う。

・読みの速度が2割ほど落ちている
 これはgccでコンパイルした弊害だと思うが、正直分からない。プロファイルを利用した最適化をしないと速くならないんじゃないかと思う。あとMakefileにiccみたいなことが書いてあったので、高速化したい人必須のインテルコンパイラを使っているためだと思われる。

・何か変わったか
 あまり変わった感じがしないが、十数手目以降の読み筋が逐次報告されるようになっている。これはクラスタリング化する際に情報を伝えるための工夫だろうか。

・メモリの使用量
 ちょうどパッチを当てた当たりにかいてあったが、最大2GBか、トータルメモリの4分の1ぐらいなので、8GB積んだPCでは2GB使うだろうが、自分の場合は3.6GBぐらいなので900MBぐらい。実際には600MBぐらいしか使われていない模様。

・マルチスレッド
 2chではGPSは1コアで動くみたいなことを言われているが、GPSはCPUの個数を調べて勝手にマルチスレッドで動くのでCPUが多ければ多いほど早くなる。ただし、悪名高きHyperthreadingなCPUを搭載している場合に、スレッドが待たされる場合が増えるので逆に悪くなる場合がある模様。コンパイルオプションでSIMD最適化
するようにしたらHTでも遅くならない気はするが、持ってないのでよくわからない。

・GPSが使うバイナリについて

GPSは3つのバイナリを使う

-rw- 60 2013-07-27 01:04 eval.bin
-rw- 74 2013-07-27 01:04 joseki.dat
-rw- 68 2013-07-27 01:04 progress.txt

dataフォルダに入ってるこれらを参照するが、サイズを見てもらうと分かる通り、Cygwinの環境で作られる仮想シンボリックリンクエミュレートファイルになっている。中身を見るとパスがかいてある。

なのでOSL_HOMEを変えると、配布されているGPSがクラッシュして動かなくなる弊害がある。

単にこの場所に参照元のファイルをコピーすればいいだけだと思うが、まだやっていない。
なお参照元のファイルはgpsshogi/dataにある。

さらにjoseki.datはjoseki-wide.datのほうを使っている模様。

■で、強いのか

試しに先手Blunderの2011年バージョン,後手GPSFISHで30秒、先読みなしで戦わせた
PCが1台であるので先読みは無し。

結果はGPS惨敗。寄らない無理攻めと筋の悪い金銀打ちがたたって大敗だったのだが、読み筋的には「いける」と思っていたらしく、大駒4枚取られてやっと、「やっぱわるかったか」みたいな評価になった。

棋譜を残すのを忘れていた。
後手番のGPSがある局面で8八金打ちをしたのだが、これが大悪手もいいところで、プロなら指さない手だと思われる。そこから寄るわけでもないのに龍を切るとかひどい手順のオンパレードだった。

むしろBlunderのほうが正しかったといえる。

GPSの場合、クラスタリングで馬鹿みたいに読めばアホな手を指さないだろうというスタンスなので、単一PCで十数手ぐらいしか読めないのではあまり意味が無い。

また12手ぐらいなら10秒ぐらいで読み切り、そこから、1手増やすごとに馬鹿みたいに読む量が増えて遅くなるので、30秒でも15秒でもあまり変わらない感じがする。逆に10秒を5秒にすると明らかな悪手がある。

対局させてみるとBlunderはプライマリとして、怪しいけど複数の手順を考慮とか、要らない手は思い切って読まないとか、一目の手順は考えないとか工夫が見られる。

一方でGPSはセカンダリなので、馬鹿正直に毎回30秒考えて指すようにしかなっていない。

まあ、結局のところ、ビルドするより配布されているのを使ったほうが楽だし十分であるという悲しい結果であった。

ただ、定石ファイルがアップデートされているので、むしろファイル挿し替えるだけでもいいのではないかとも思うがよくわからない。対戦に不向きと書いてあるのはそういうことなんだろう。

pythonにprivate変数がない件 [プログラミング]

お前そんなことも知らないでpython信者自称してんのかと言われると「はい、すいません」としか言えない。そんな話。

そもそもpythonとかのLL言語でクラスなんて書きたくねーし。というぐらい手続き脳。
一応C++の魔界の入り口にたったことがあるぐらいのシャチレベル拳士。

で、ちょっと調べてみると、確かにpythonでは隠蔽できないよみたいなことが公式に書いてある。
くっ、我らがpythonがなぜ・・・と思ったが、9.6にルール的なものが書かれていた。

http://docs.python.jp/2/tutorial/classes.html#tut-private

9.6. プライベート変数
オブジェクトの中からしかアクセス出来ない “プライベート” インスタンス変数は、 Python にはありません。

ガーソ。

よく読むと解決方法はその後に書いてある。

・頭に1個だけアンダーバーをつける
 これはpythonの慣習でアンダーバーがついていたら非publicだと(人間が)思いなされ

ちょっとこれは俺が思う最強のpythonとしては理解し難い。pythonって誰がどう書いても同じコードになってしまううぅぅぅっていう強い制約がpythonらしさだと勝手に思っていたので、ちょっとなーっていう。

・頭に2個アンダーバーをつける
 こっちは割と妥当。これをやるとネームマングリング(C++の関数名とか変数名のアレ)が発生する。がC++のそれと違って命名規則が決まっている
 具体的には __x とすると _クラス名__x となる。だから意図的にわかっててアクセスするとアクセスできてしまう。

class Klass:
    __x = 10
    def __init__(self,value):
        self.member1   = value
        self._member2  = value
        self.__member3 = value

instance = Klass("ahaha")

print "member1=",instance.member1
print "member2=",instance._member2
print "member3=",instance._Klass__x
print "member3=",instance._Klass__member3


最後の2行が意地悪アクセス。こういうのを「禁止」できないのが、隠蔽できないという理由だが、まあ__member3と書いて文句言われるぐらいなら隠蔽はできなくてもいいよね。(信者脳)。

勉強になった。

信者が勝手に推測すると、アクセスできるかどうかを真面目に実装すると重いからパフォーマンス重視的にはやりたくないんじゃなかろうか。ナイスな実装案が提案されたらpython4とかでできるようになるかもしれない。

pythonでsha1を計算する方法 [プログラミング]

前に.NetのPython(名前忘れた)使ってハッシュ計算してみた時に、ファイル全部読んでハッシュ計算するという富豪的プログラミングをしてみたところ、300MB付近でOOMっぽい動きをしてしまって動かなかった。
原因は.net pythonのバイナリ列の実装に使っているStringクラスの制限のようだったのでまったく放置していた。
cpythonでは特にそういう問題もなかったし。

ただ、本来であれば分割して処理するのが筋であろうということで、調べたところ、以下の様なコードが正しいようだ。

def calculate_hash( fullpath ):
	f = open(fullpath, 'rb')
	h = hashlib.sha1()
	while True:
		d = f.read(64*1024) #64KB
		if( d ):
			h.update(d)
		else:
			break
	f.close()
	print 'sha1 :' + h.hexdigest()
	return


ここでいうdが一気読みだとファイルサイズ分のバイト列になっているのが問題だった。

ハッシュ計算するsha1とかのアルゴリズムは、LinuxKernelやopensshの実装見てもわかるように3つの関数しか必要ない

init
update
final

で、pythonのようなスクリプト言語だとinitみたいなのはコンストラクタに入っているし
finalはhexdigestのような出力関数が呼ばれた時に実行されるのであろう。

またLinuxKernelなどでは一発読み込み対応で、init/update/finalを全部実効する関数も用意はされている。
ただ、今回のように読みこませるファイルが数百MBとか数TBとかの可能性がある場合は、init/update/finalを適切に呼び出す必要がある模様。


SyntaxHighlighter [プログラミング]

ゲームだプラモだデジカメだオーディオだと趣味満載のBlogだがたまにプログラムのメモっぽいことを書こうとした時に、このBlogは改行を残してくれないので非常にめんどくさい事が多く割と書かなかったが、GWであるのもあってちょっと調べてみた。

SyntaxHilighterというのがあるらしい

http://konoha-webnote.blog.so-net.ne.jp/2012-11-28

ここのやりかたを丸パクりしてやってみた
ただ、参照jsにbashが無いので追加した。

bash

#!/bin/bash

CNT=1
MAX=10
while [ $CNT -lt $MAX ] ;
do
  echo $CNT
  let CNT+=1
done


c

/*
    make -C /lib/modules/`uname -r`/build M=`pwd`
    see kernel/kmod.c
*/
#include <linux/module.h>
#include <linux/kmod.h>

char usercmd[256] = "/bin/ls";

static int __init call_user_init(void)
{
    int ret;
    char *argv[] = { usercmd, NULL };
    char *envp[] = {
        "HOME=/",
        "TERM=linux",
        "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
        NULL
    };
    ret = call_usermodehelper(usercmd, argv, envp, UMH_WAIT_PROC);
    if (ret) {
        printk(KERN_INFO "call_user_init fail=%d\n", ret);
    }
    return ret;
}

static void __exit call_user_exit(void)
{
    printk(KERN_INFO "call_user_exit\n");
}

module_init(call_user_init);
module_exit(call_user_exit); 


でbashのキーワードであるwhileとかletに色が付くはずなんだが、付かない。
preタグは聞いているがfunctionが効いていない
単にpreタグが動いているだけの模様。
というか、そもそもpreタグが使えたのでそれを使えばコードは貼れる模様。
#includeはTwitterのタグに反応しているので、どうもSo-netのスクリプトと競合しているような・・・

うーん。微妙。
前の10件 | - プログラミング ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。