スキップしてメイン コンテンツに移動

投稿

C++: インテル スレッディング・ビルディング・ブロックを使って簡単に並列化

最近はマルチコアCPUが当たり前になってきて、それを使って簡単に並列処理プログラミングができないか、頭を悩ませていたのだが、インテルのスレッディング・ビルディング・ブロック(Threading Building Blocks, TBB)が非常に良くできた技術であることを知った。 これまではMPIやら、OpenMPやら、CUDAやらをちょろちょろ手を出しつつも、どれも正直面倒だった。趣味のプログラミングではそれでも楽しいからいいのだけど、単にある処理を並列化で高速にしたいだけの場合、並列処理に関わる面倒な手続きなどは極力省きたい。また、どうしても泥臭いやり方になることが多い。例えば、Cでは簡単に書けるのだけど、C++の機能を使った処理がやりづらかったりね。 そこで、TBBが登場する。マルチコアやメニーコアプラットフォーム上での利用となるが、最近では一般のノートPCでさえマルチコアCPUが使われていることを考えると、世にある様々な並列処理環境のうち、マルチコアCPUでの並列化がもっとも望まれているだろうと思う。実際、自分もマルチコアCPU上での並列処理が簡単にできないものかとよく考えていた。それに、従来の泥臭さの残る並列化に比べて、C++テンプレートによるコーディングスタイルはスマートだ。 さて、TBBを利用するには TBB公式サイト からダウンロードしてくればよい。オープンソース版が用意されているので、それを使って自由にプログラムを作成できる。また、このサイトにはチュートリアルやリファレンスも用意されている。さらに、日本語版のドキュメントも XLsoftのTBBサイト から利用できる。ここのチュートリアルを一通り読めば大抵の場合で利用できるようになるだろう。 今回は、「 はじめてのCUDAプログラミングで分子動力学計算 」で作成したC++版のなんちゃって分子動力学(MD)計算プログラムをTBBを利用して並列処理を行ってみた。非常に簡単だった。相互作用計算の関数を関数オブジェクトに変更しただけだ。TBBについて知っていれば5分もかからないかもしれない。こんなに簡単に並列化ができるのであれば、もっと早くに知りたかった。まあ、百聞は一見に如かず、今回使ったコードを下に示す。青(水色)で示した部分が書き加えたコード、赤(ピンク)で示した部分が削ったコード、水...

プログラミングができるということは、人生を楽にできるということ

どのようにプログラマになったのか知るのは面白く、興味深い。そして、プログラミングに対するの様々な考え方や捉え方を知り、それを自分の知識に加えるのが楽しい。そこで自分自身がどのようにしてプログラミングを学んできたのか、そしてプログラミングについてどのように考えているのか述べたいと思う。たいした内容でもないが書いているうちに長文になってしまった。取り敢えず概要だけを知りたい方は、それぞれの段落の最初の文章を読めば何となく分かると思う。 最初のプログラミング 初めて触れたPCは、父親が購入したNECのPC-8801mkIIだった。当時のPCには最初からBASIC(N88-BASIC)が付属しており、これを使って手軽にプログラミングができた。ただ、BASICはインタプリタであり、当時のPCの性能と相まって処理速度が非常に遅く、高速化のためにはアセンブラが必要だった。そこで、父親の書籍を漁りつつ、ニーモニックをハンドアセンブルでマシン語に変換したりもした。 しかしながら、BASICのプログラミングですら当時の自分にとってはとても難しく感じた。その頃読んでいたマイコンBASICマガジンに載っていたプログラムのようなコンパクトでエレガントなコードに比べ、自分のコードはなんて拙くて汚いのだろうと何度も思ったものだ。結局、プログラミングはセンスがある人だけのもので、自分には無理なのだろうかとさえ考えた。あるアイデアがあっても、それを思ったようにコードに落とせないのだ。毎回リファレンスとのにらめっこになる。それでも何とか書き上げたコードは不必要に肥大であり、分かりにくく、あちこちからバグが顔を出していた。 それでも、不細工だろうが何だろうが、プログラムが完成するのはとても嬉しいことだった。自分の力でゼロから何かを作り上げるという行為は本当に楽しかった。後に気が付いたことだが、プログラミングはセンスなんかよりも、この「楽しい」という気持ちの方がよほど重要だったのだ。センスがあっても楽しくなければ長くは続かないだろうし、楽しいと思っているのならば小さな積み重ねが経験となり、知識となっていく。 ただ、その当時はプログラミングばかりをしていたわけではなかった。PCゲームにもはまっていた。オールマシン語が売り文句の一つだった頃だ。そして、その頃のゲームソフトは個人もしくは少数...

C++: ストリームの出力先をファイルや標準出力に切り替える

C++のストリームの出力先を任意にファイルや標準出力に切り替えたいときがたまにある。しかし、その度に標準出力ストリームやファイルストリームを定義し直して使うのは面倒だし、効率が悪い。 そんな時は、以下のコードで示す方法で切り替えると楽だ。2~3行で変更できる。さらに、ostreamのポインタでストリームを保持しておけば動的な切り替えも簡単だ。 以下、ソースコード。 #include <iostream> #include <fstream> using namespace std; int main() { // coutの出力バッファをofstreamのバッファに変更する方法. // 最後にcoutの出力バッファを元に戻すこと. streambuf* last = cout.rdbuf(); ofstream ofs("test01.txt", ios_base::out); cout.rdbuf(ofs.rdbuf()); cout << "test01 to file" << endl; ofs.close(); cout.rdbuf(last); // ostreamのインスタンス作成時にストリームの出力バッファを指定する方法. ofs.open("test02.txt", ios_base::out); ostream out1(cout.rdbuf()); ostream out2(ofs.rdbuf()); out1 << "test02 to stdout" << endl; out2 << "test02 to file" << endl; ofs.close(); // ostreamのポインタを使ってnewでインスタンスを作成する方法. // これなら必要時に動的にストリームを変更できる. ostream* o; o = new iostream(cout.rdbuf()); ...

Python: URL短縮サービスbit.lyのAPIを使ってみた

最近、 TwitterがTinyURLを捨ててbit.lyを採用 したらしい。そんなこともあって、URL短縮サービスに興味がわいたので、以前にGoogle App Engineで作成した Twitter送信機能付きメッセージボード で書き込んだURLをbit.lyで短縮して送信できるようにしてみた。今まではURLを含む投稿はTwitterに送信しないようにしていた。以下にbit.lyのAPIをPythonを使ってどのように利用すればよいか書いてみる。 まずは、 bit.ly で無料アカウントを取得する。これで API Key が貰えるので、bit.lyのAPIを利用できるようになる。次に、 bit.ly APIの解説 を参考にしながら、APIを使ってみる。URLの短縮も展開も簡単だ。JSONでもXMLでも利用できるが、今回はsimplejsonを使ってJSONを利用している。 詳しくは最後にソースコードを付けたのでそれを読んで欲しい。因みにソースコード中の赤字で示した部分がアカウント名とAPI Keyになる。コード中のアカウントはbit.lyのデモ用なので、自分のアカウントと置き換えて欲しい。使い方は、 bitly_test.py URL とすればよい。URLが短縮URLなら展開され、通常のURLなら短縮URLが表示される。 また、Google App Engineで利用する場合は、simplejsonを from django.utils import simplejson として呼び出し、urllib2.urlopenをurlfetch.fetchに変更すればよい。 bitly_test.py #!/usr/bin/env python import sys, os, re, urllib, urllib2 import simplejson apiurl = "http://api.bit.ly/%s?version=2.0.1&%s=%s&login= bitlyapidemo &apiKey= R_0da49e0a9118ff35f52f629d2d71bf07 " api_index = { "shorten": "longUrl...

Python: 複数の画像ファイルを余白を埋めるように貼り付ける

何か面白いコードが書きたいなぁ、と思ってPython+PILで複数の画像ファイルを適当に余白を埋めるようにキャンバスに貼り付けるプログラムを書いてみたけどあまり面白くなかった。それでもせっかく書いたので一応公開する。 まず、入力した画像ファイルすべての面積を取得して、その面積と出力画像の面積の比を求める。すべての入力画像に対して、その比から大きさを変更する。これで入力画像の面積の総和と出力画像の面積が等しくなる。次に、入力画像を面積の大きい順にソートし、入力画像一つ一つと出力画像を重ね合わせ、もっとも余白との一致が大きい場所を見つける。その場所に入力画像を貼り付ける。貼り付ける際、全体の余白を少なくするために画像の大きさをランダムに1.2~1.5倍に拡大している。すべての入力画像を貼り付ければ完了だ。 ここの画像は フリー画像素材EyesPic に置いてあった植物写真の22枚を貼り付けてみたものだ。プログラムの使い方は、 place_pictures.py 出力画像ファイル 複数の入力画像ファイル... のようにする。例えば、同じディレクトリにあるすべてのJPEGファイルをimage.jpgに貼り付ける場合、以下のようにすればよい。因みにデフォルトでは600×800ピクセルの大きさの画像となっている。コード内のXSIZE, YSIZEを指定することで自由に変更できる。 place_pictures.py image.jpg *.jpg 以下にソースコードを示す。 place_pictures.py #!/usr/bin/env python import sys, os, glob, math, random, Image IMAGE_EXT = (".jpg", ".jpeg", ".jpe", ".png", ".bmp", ".gif", ".tif", ".tiff") IMAGE_XSIZE, IMAGE_YSIZE = 600, 800 def place_pictures(files, img_file): area = 0 sorted_...

NW-X1060を購入

プログラミングをしているときに一つ気になることがある。それはPCから出るノイズだ。特に自分は職場でも自宅でも周りを数台のPCに囲まれているのでその音も馬鹿にならない。聞いているうちに何となく慣れてしまうのだが、常に耳に届くノイズは少なからずストレスになっているような気もするのだ。それもあって、ノイズキャンセリングヘッドフォンは複数所有している。 最近、デジタルノイズキャンセリング機能を有したSonyのウォークマンNW-X1060が発売されたことを知った。フラグシップモデルらしい。高性能ノイズキャンセリング機能と聞くと食指が動く。しかも、無音のままノイズキャンセリング機能だけを働かせることができるらしい。今回もそれが大きな動機となって購入してしまった。 所有しているノイズキャンセリングヘッドフォンは、BOSEのQuietComfort2、SennheiserのPXC300、SonyのMDR-NC22など。ほかにも安物のノイズキャンセリングヘッドホンがあったりする。今回はデジタルノイズキャンセリングと云うこともあり、それらと比べてもなかなかの性能を発揮しているようだ。自分の周りのPC環境で使うと、それまでうるさかったノイズがすぅーっと消えるのが心地よい。 コーディングしているときに使ってみたが、音質が良く、長時間の使用でも聴き疲れがないのがいい。今までのものは耳が疲れてしまってコーディングなどの作業に集中ができなくなったりしたが、今回のものは疲れにくいようだ。それと、電車通勤時に動画を視聴するのにも便利。画面は小さいけどね。でも、かさばらないし、有機ELなので画質はかなり良い。 欠点としては、やはり付属のソフトウェア(SonicStage)が使いにくいことと、本体にストラップがつけられないので胸ポケットなどに入れて使うしかないこと。別売りの専用ケースを使えば良いそうだが、このぐらいは初めから付けて欲しかった。SonicStageは相変わらずだ。ソフトウェアの使い勝手が良くなるだけでだいぶ印象も変わるだろうに。NW-X1060自体の使い勝手はまあこんなものか? 特に比較する対象も持っていないので何ともいえない。 結論としては、思ったよりも音が良く、聴き疲れもしないし、デジタルノイズキャンセリングも効果があり、購入して良かったという感想。まあ、音の聞こ...

C++: 編集距離を求めるアルゴリズム

編集距離(edit distance)とは二つの文字列がどの程度異なっているかを示す数値であり、 レーベンシュタイン距離(Levenshtein distance) を指すことが多い。文字の挿入、削除、置換それぞれを一つの操作として必要な操作の最小数を求めるものだ。例えば、kittenとsittingの編集距離を求める場合、下記のように3回の操作でkittenをsittingに変更できるので編集距離は3となる。 1. sitten (k を s に置換) 2. sittin (e を i に置換) 3. sitting (g を挿入) そこで今回は編集距離を求める複数のアルゴリズムについてC++で実装してみた。 動的計画法 編集距離を求めるもっとも一般的なアルゴリズムは、動的計画法(dynamic programming)だろう。計算時間はO(mn)であり、手軽だ。C++で書いたコードを下に示す。尚、コード中に出てくる定数SIZEは扱う文字列にあわせて適当に決めておく。動的にメモリを確保することもできるが処理が遅くなるので、あらかじめ決め打ちしておく方が効率がよい。 int edit_distance_dp(const string& str1, const string& str2) { static int d[SIZE][SIZE]; for (int i = 0; i < str1.size() + 1; i++) d[i][0] = i; for (int i = 0; i < str2.size() + 1; i++) d[0][i] = i; for (int i = 1; i < str1.size() + 1; i++) for (int j = 1; j < str2.size() + 1; j++) d[i][j] = min(min(d[i-1][j], d[i][j-1]) + 1, d[i-1][j-1] + (str1[i-1] == str2[j-1] ? 0 : 1)); return d[str1.size()][str2.size()]; } O(ND)アルゴリズム 追記 (...