企業の研究者をめざす皆さんへ

5月 4th, 2010 by tune No comments »
企業の研究者をめざす皆さんへ―Research That Matters
丸山 宏
近代科学社
売り上げランキング: 131342
おすすめ度の平均: 4.5

4 IBM東京基礎研究所のようす
5 企業研究者を目指す学生は勿論のこと、企業研究者にも参考になる。

この本を読んでいてどこか既視感があったのですが、情熱プログラマー ソフトウェア開発者の幸せな生き方
に通じるところが非常に多い本です。情熱プログラマがソフトウェアエンジニアのキャリア構築について述べた本なら、こちらはリサーチエンジニアのキャリア構築について書かれた本です。必要とされる技術やバックグラウンドが多少異なるのかもしれませんが、世界基準で力を蓄え、世の中を大きく変える創造性を求められる点で抑えておくべき素養は似通ってくるのかもしれません。

本の冒頭部では研究者は「ものごとの原理に常に立ち返って真理を追求する姿勢を失ってはならず」かつ「お客様や社会の問題を常に意識して、それを解くための真理・原理・仕組みを考えていく」必要があると説いています。これから先自分の仕事が仕分けされないようにするには研究者としての本分を忘れず、世の中に貢献していく姿勢が求められます。研究者の貢献と言うと最近ではイノベーションという言葉で曖昧に表現されている感がありますが、この本では「どんな形であれ、インパクトの大きさで測られるべき」としています。Appleが出すようなセクシーな製品や、TEDで見れるような数年先の未来モデルだけではなく、Linuxのような世界中で使われるソフトウェアを開発することも立派なインパクトの一つとしています。この定義はこれまで「インパクトのある大きいことをやれ」とただ言われていただけに感じていた自分には
納得感が有るものでした。

その他、研究者として自らを伸ばしていくためにいくつものアドバイスがあります。

  • 目標となる人物・師を探すこと
  • 解くべき価値がある、いい問題を見つけること
  • 成果はすぐに使われない可能性があるので、きちんとした形(論理性のある文書、例えば論文)で残しておくこと。
  • コミュニケーションとは相手に”納得”してもらい、相手に次の行動を促すこと。
  • 見えないことはいないのと同じ。存在感を出すこと。
  • 外の世界を積極的に経験すること。

研究者としてのアドバイスの他に、IBM社内での取り組み事例が各所で紹介されていて、IBMという組織の巨大さ、底力を垣間見ることができます。自分が知っていたIBMとはずいぶん違う点もあり、ここも面白く読むことが出来ました。

大学で研究室に配属されたばかりの学生や、企業に就職して研究開発部門に配属された新人社員が読むと得られるものが多いと思います。この本はIBM東京基礎研究所内のイントラブログをつなぎ合わせる形で構成されていますが、複数の文書をつなぐために記述が冗長な所も見受けられます。もっと多くの人に読まれていい本だと思うので第2版が出るならこの点が改善されるといいなと感じました。

・・・

ちなみに自分の本は丸山さんからいただいたサイン付きです♪

Apple StoreでMacBook Whiteのパームレストを交換

5月 4th, 2010 by tune No comments »

APPLE MacBook 2.26GHz 13.3インチ 250GB MC207J/A

MacBookのパームレストにひびが入り、下の基板が見える状態になっていたので渋谷のApple Storeに行って修理してもらいました。MacBookのパームレストにヒビが入る問題は発売頃からあったようで、ネットで探すと同種の現象がすぐに見つかりました。Appleもこの件は不具合として認めているようで、無償で修理してくれるそうです。ただし郵送でPCを贈る必要があり、PCがない生活がしばらく続くのは不便なのでApple Storeに持ち込んで修理してもらいました。

修理までの流れはこんな感じでした(A:Apple, 自:自分)

前日

  • 自:Appleのお客様窓口に電話
  • 自:症状を説明、無償で修理してくれる旨を向こうから聞く
  • 自:郵送で修理は嫌なのでApple Storeで修理出来ないか、こういう事例もネットで見かけた。
  • A:Appleのお客様窓口とApple Storeのジーニアスバーは連携していない。なので別途お客様から連絡して貰う必要がある。
  • 自:キーボードの交換在庫ぐらい確認出来ないのか?
  • A:できない、ジーニアスバーの予約なら代理で出来る
  • 自:ならそれでOK、渋谷店で予約をお願いする。
  • A:連絡用に電話番号とメールアドレスを教えて欲しい
  • 自:Appleに製品登録したときに使ったのでいいよ → 予約確認などの案内は送られてこず。

当日

  • 自:Apple StoreにPCを持ち込んで再度説明
  • A:無償で修理させてもらう。修理時間は6時間ぐらい
  • 自:そんなにかかるの? まあいいけど
  • 自:GW中の渋谷で6時間もブラブラして時間をつぶし、Apple Storeで修理されたMacを回収

無償で修理してくれたことに着目するとAppleの対応は良かったって思いがちだけど、よくよく考えてみるとあまりAppleの対応は良くないと思う。そういえばSnow Leopardのインストールメディアも初期不良で、Appleは無料で交換してくれたけど、その時は船便で10日ぐらいかけて送ってきたことを思い出した。
紆余曲折がありSnow Leopardへ » tune web

Apple製品で言うと、妻が使っているiPhoneは画面右上にあるボタンが最初から陥没していて非常に押しづらくなっている。自分にとってAppleの品質面の印象はかなり悪くなっている。前に使っていたThinkPadは最後まで問題を起こすことはなかった。あのレベルまでは求めないけど、もうちょっと何とかならないものだろうか。

BREEの日焼け状態 2010

5月 3rd, 2010 by tune No comments »


細々と不定期連載を続けている愛用ヌメ革製品の日焼け状態をさらす日記です。以前のものはBREEタグをつけた日記一覧で見ることが出来ます。


まずはカバン。相変わらずしっかりしていていますが、使用頻度が落ちているからかもしれません。一度雨の日があるとカバンを取り替えてしまい、翌日以降晴れていてもこのカバンを使わないことが多いです。日焼けは前とそんなにかわりないかも。


色が濃くなっているのはこの財布が一番。毎日使っているからか、手垢がつくからか手入れをする度に汚れがたくさん落ちます。ところどころ痛んできていますが、まだまだ使えそうです。鞄と同じく4年選手です。


一番使用頻度が低いのが名刺入れ、研究開発職だと名刺交換をする機会が少なくてついつい鞄の中に入れたっきりにしてしまいます。もうちょっと使ってあげないとな。

せっかくなので色の変化を時系列で並べてみました。こんな感じで色がついていくという参考になれば。
◯2005年12月
2005_12230004.JPG

◯2006年8月
dscf0608.JPG

◯2007年4月
dscf0718.JPG

◯2009年5月
BREEの日焼け状態

◯2010年5月

Windows/Linux両環境で動作するC言語ソースの一元管理をGitで行う

5月 2nd, 2010 by tune 1 comment »

gitでリポジトリからのチェックアウト時に文字コードを変換する » tune webの続きです。
【未解決】VisualStudioとgccでコンパイルできるソースのエンコーディング » tune webでも書きましたが、問題はVisualStudioはUTF-8 BOM有のみ、gccはUTF-8 BOM無しのみ扱え、両者で問題なく扱える文字コードが存在しない事でした。gitにあるsmudge/cleanを使うとチェックアウト/ステージ時に任意のフィルタを通すことができ、BOMの除去をここでやれば出来そうなのですが、文字コード変換ソフトのnkfではBOMの有り無し以外も書き変わってしまうことがあるため実用に使えなかったのがこれまででした。

git smudge/cleanはPro Git – Pro Git 7.2 Git のカスタマイズ Git の属性に詳しく解説されています。
git smudge/cleanの設定は前の日記に書きましたが、ここでも引用しておきます。

まず.gitconfigファイルに以下を追加

[filter "fixbom"]
clean = “/usr/bin/bom_util -a”
smudge = “/usr/bin/bom_util -d”

これでsmudgeでUTF-8 BOM無し、cleanでUTF-8 BOM有りになります。

これだけではダメで、フィルタ処理をかけるファイルを指定する必要が有ります。
gitの管理フォルダである.gitがあるトップディレクトリに.gitattributesファイルを以下の内容で作成し、git checkout -fします。

*.c filter=fixbom
*.h filter=fixbom

/usr/share/git-core/templates/info/attributes を作って上記内容を書いておくとclone時に.git/info以下にコピーされてgit cloneしただけで文字コード変換が動くようになります。

上記で指定している、BOMをつけ外しするプログラムは結局自作しました。単にファイル先頭のBOMを検知して追加・削除をするだけです。ハマったこととしてgit smudge/cleanのデータは標準入力から渡され、標準出力へ書いた内容で差し替えられます。外部コマンドとして起動されるのかと思っていましたが異なるようです。
BOMをつけ外しするプログラムを下に貼っておきます。(gistはこちら→gist: 386410 – GitHub)

#!/usr/bin/ruby

require "optparse"

mode = :help

opt = OptionParser.new
opt.on("-a", "Add BOM"){|v| mode = :add}
opt.on("-d", "Delete BOM"){|v| mode = :delete}
opt.parse!(ARGV)

case mode
when :add
 STDOUT.binmode
       lines = readlines
       unless lines[0] =~ /^\M-o\M-;\M-?/ then
               print "\xEF\xBB\xBF"
       end
       print lines

when :delete
 STDOUT.binmode
       lines = readlines
 lines[0].sub!(/^\xEF\xBB\xBF/, '')
 print lines

when :help
       STDERR.puts opt.help
end

VisualStudioでの開発をメインにしているので、リポジトリ内のソースをUTF-8 BOM有、改行コードをLFCRにして運用しています。
これでLinux環境での開発がひとつやりやすくなりました。

入門Git 入門git 実用Git

Google Cloud Printに関する解説

5月 1st, 2010 by tune No comments »

少し前に発表されたGoogle Cloud Print構想ですが、まだ動くものがないせいか最初のニュースリリース以来何の進展もないのが現状です。

TechCrunchが一番詳しく報じていましたが、それでもGoogle Cloud Printが何をしてくれるのか、現状どういう状態にあるのか知ることが難しかったので元情報にあたってみました。そんなに難しい英語ではありませんが、後で参照することを考えて訳も残してあります。きちんと原文と対応する訳ではありませんが、参考にはなるんじゃないかと。

Google Cloud Printって何?
Webブラウザ/デスクトップアプリ/携帯端末全てから、ドライバの問題を気にすることなく世界中全てのプリンタに印刷出来るようにすることを目指すGoogleのプロジェクト。
GoogleはCloud Printのデザインドキュメントとプロトコルを公開し、さらにCloud Print Serviceを将来公開する。 アプリケーションは印刷指示をOSやドライバに送る代わりにGoogle Cloud Printに印刷ジョブを送る。Google Cloud Printが登録されている適切なプリンタにジョブを送り、アプリに印刷状況を伝える責任を果たす。

Googleがこのプロジェクトに取り組むのはChrome OSで全てのプリンタに対応するドライバを用意することが不可能だから。Chrome OSはCloud Printを使うように設計される、プリンタドライバは一切搭載されない。

現状何があるの?
Googleがこんなこと考えているよというデザインドキュメントだけ。
数ヶ月以内に追加の発表があるかも。

この段階でCloud Printを発表したのはプリンタメーカーとコミュニティの協力/フィードバックを早期に得るため。

どうやって実現するの?

Cloud Printではクラウド対応のプリンタと、レガシープリンタの2種類のプリンタを想定している。現在世の中にあるプリンタはWeb連携していてもレガシープリンタに分類される。Googleの考えるクラウド対応プリンタとはCloud Printで想定しているプロトコルを解釈出来るネットワーク対応プリンタを指す。かといって全てのプリンタがクラウド対応になるのを待ってるわけにも行かないから解決策も提供する。それはGoogle ChromeにCloud Printのプロトコルを解釈出来るプロキシを搭載することである。これにより、Google Chromeユーザは既存のレガシープリンタをPCをプロキシとして、Google Cloud Printのサービスを利用することが出来る。かといってこの方法だとPCもプリンタも常時電源をつけていなければならないので、例えばルータでプロキシが動くようにすればこの問題を解決出来ると考えている。(Google Cloud Printの絵にルータが書いてあるのはこのため。)

もう少し詳しい技術情報を
ユーザとプリンタの関連付けはGoogleアカウントを用いる。ユーザは既存のアカウントでログインし、はじめに利用するクラウド対応プリンタ(またはプロキシ下のレガシープリンタ)を登録する。プリンタはGoogle Docsのドキュメントのように扱うことができるので、プリンタを複数のユーザで共有することも簡単。

Cloud Print Serviceとプリンタの会話はHTTPで行う。サービスでは以下のAPIを定義

  • register : プリンタの登録
  • update : プリンタ情報の更新
  • list : 特定ユーザが利用可能なプリンタ一覧の取得
  • delete : プリンタの削除
  • control : プリントジョブの状態取得
  • fetch : 次のプリントジョブの取得

出力はjson, xml, textを選択することが出来る。

プリントジョブは永続化したXMPPコネクションを使ってGoogle Talkサーバから通知される。定期的にサーバからfetchしてもOK。

印刷データはfetch APIの出力に記載されているfileUrlから取得出来る。プリンタはfileURLにアクセスした際のHTTPのMIMEタイプを見て直接印刷可能かを判断する。 出来なければfetch APIに記載されたticketURLの方をアクセスし、PDFでデータを受け取ることができる。 当初はPDFのみをサポートするが他のフォーマット(例えばXPS)も将来サポートするかも知れない。PDFへの変換はGoogle Cloud Printが担当する。

雑感
Googleの今ある技術をうまく組み合わせてプリントジョブ管理の仕組みを作ってきたなという印象です。

プリンタドライバはジョブ管理以外にレンダリングなども担当していますが、この処理はプリンタ側に組み込む必要がありそうです。コピー機ぐらいのリソースがあれば問題ないかもしれませんが、1万から2万ぐらいの安いプリンタではリソースが厳しそうです。いずれにせよやるとなったら値段が高い方の機種から対応が進んでいくでしょう。

PDF内のデータは表示順に並んでいないと聞いたことがあります。1ページ目にある画像がファイルの後ろに格納されていると言った具合です。これではプリントジョブを受け取りながら印刷できないのでプリンタ側で一旦記録バッファリングしなくてはいけません。プリンタにはどれぐらいメモリの余裕があるんでしょう。

あとプリンタがGoogleアカウントと結びつけられるのは便利そうですが、近くに無いプリンタに出力してしまうこともよくありそうです。自宅の印刷物を会社のプリンタに出したりしては問題だと思うのですがどうするんでしょう? コピー機ではセキュアプリントなどと言った名目で、印刷ジョブを出した人がその場に行ってボタンを押さないと実際に印刷を行わないようにできます。こういう機能が一般的になるんでしょうか。

いずれにせよクラウド対応プリンタを実現するには、これまでよりもプリンタ側で製造コストをかけないとダメそうです。逆に言うとプリンタで使えるリソースが増えるのでこれまでは出来なかったことも考えられるかもしれません。プリンタメーカー各社にはピンチではなく、チャンスと思って色々考えて欲しいですね。

AdobeはなぜComputational Photographyに注力するのか

4月 23rd, 2010 by tune No comments »

a canon camera
Creative Commons License photo credit: lett -/=

最近Adobeのニュースが賑わっています。CS5の発表もありましたが、多くはAppleとやりあっているFlash関連のニュース。とうとう先日AdobeはiPhone/iPad向けのFlashから手を引き、Androidに注力することを宣言しました。業績が好調のAppleがAdobeを買収するのではという憶測も定期的に出てきています。

AdobeはFlashを共通のミドルウェア化することでWebの覇権を取りに行こうとしていますが、Flashそのものでは利益を生めません。Flashをオーサリング出来るAdobe Flash、さらにはPhotoshop, Illsutratorを買ってもらってソフトウェアで利益を上げるビジネスだと自分は認識しています。MicrosoftがOfficeの値段を下げる中、AdobeのPhotoshopはアップグレードでも48300円するそうです。まとめて購入するとMac Proが買えるぐらいの金額になります。

これだけ高いお金を払ってもらうには相応の機能が必要と考えるのが一般的です。Adobeは今回のCS5で様々な目に見える機能を実装しています。「えげつない」と評されたPatchMatchは話題になりました。

こういった新しい技術はCG技術を画像処理に応用する”Computational Photography”に分類されます。一口にComputational Photographyと言っても色々アプローチがあって、SIGGRAPHなどの有名な国際会議で活発な研究成果の発表を知ることが出来ます。Adobeは世界で最も”Computational Photography”に注力している企業の1つです。なんですが…なんでAdobeがこんなに注力するのかが自分にとって謎でした。Photoshop/Illustratorに最新の画像処理技術を組み込んでさらに魅力的にして、CS6, CS7とアップデートしてもらうのも1つの理由でしょう。でも”Computatioal Photography”は特殊なハードウェアを要求するものもあり、どんなにAdobeが頑張っても実現出来そうに無いものもあります。そこが謎でした。技術の将来性があるからといって、すぐに利益を産めないものにリソースを使いすぎなんじゃないかと。

で、教えてもらったのがフランケンカメラプロジェクトです。カメラのハードウェアとソフトウェアを切り離し、ハードウェアを共通化する。その上でソフトウェアで価値を生み出せるようにするカメラ、それがフランケンカメラです。iPhoneで沢山あるカメラアプリを想像すると、このカメラでどんな可能性が広がるか伝わりやすいかもしれません。

これがあれば、Adobeはカメラメーカーになることができます。それもレンズや撮像素子は差別化要因にならず、ソフトウェアで差別化を図る必要がある「ソフトウェアで画質が進化する次世代カメラ」です。今のカメラよりも従来のデジカメとは2世代ぐらい先を行っているでしょう。こうなればComputational Photographyに一日の長があるAdobeがカメラメーカー、携帯メーカーとは異なる軸で戦うことができます。フランケンカメラにAndroidを積んで、その上で動くUI/アプリをFlashで作れるなら現実的にAppleと戦えそうな気も少しだけしてきます。

実際Adobeぐらいの規模なら業績が悪いカメラメーカーを買収することぐらいできるでしょうから違うアプローチを取るかもしれません。カシオはソフトウェアで差別化を図っていくつもりのようなので、Adobeと波長が合うかもしれません。

以上、会社の同僚から教えてもらった話でした。
間違ってる可能性の方が高いと思いますが参考まで。

並行コンピューティング技法 第6章

4月 23rd, 2010 by tune No comments »

いよいよアルゴリズムの並行化に着手する。今回は並列和、プリフィックススキャン、セレクションの3種類。

◯並列和
配列の和を全部求めるよくある処理。楽なのはOpenMPやTBBを使ってリダクション処理をそのまま利用すること。
自前で実装するなら配列をスレッド数で分割して個別に小計を計算。全スレッドが計算終わったら小計を全部足して合計をもとめるというやり方がおすすめ。

◯プリフィックススキャン
[3, 5, 2, 5, 7, 9, 4, 6]という配列を与えたときに[3, 8, 10 15, 22, 31, 35, 41]という配列を求める。配列のN番目に元の配列の0〜N番目までの和を入れておく処理に当たる。包含的プリフィックススキャンとも言うらしい。
先頭を覗いて[0, 3, 8, 10, 15, 22, 31, 35]の配列を求める排他的プリフィックススキャンの方法もある。

並列化の手法として、スレッド数で配列を分割し、個別にプリフィックススキャンを行う。次に末尾の要素を使って前後のチャンクに伝搬させる値を計算する。計算が終わったそれぞれのスレッドが担当するチャンクに値を加算してプリフィックススキャンを完了する。

さっきの例を3スレッドでやるとこんな感じになる。2と4のステップが並列化可能になる。
2から3、3から4に移るときに毎回スレッドを生成/破棄するとオーバーヘッドになるので、スレッドのイベント通知機能を上手く使って使いまわすのが吉。

1. 入力をスレッド数で分割
[3, 5, 2, 5, 7, 9, 4, 6] -> [3, 5, 2], [5, 7, 9], [4, 6]

2. 個別にプリフィックススキャン
[3, 5, 2], [5, 7, 9], [4, 6] -> [3, 8, 10], [5, 12, 21], [4, 10]

3. 配列の末尾の値で排他的プリフィックススキャンを行い、伝搬させる値を計算する
[3, 8, 10], [5, 12, 21], [4, 10] -> [10, 21, 10] -> [0, 10, 31]

4. 3で求めた値を2の処理結果にそれぞれ加算
[3, 8, 10]+0, [5, 12, 21]+10, [4, 10]+31 -> [3, 8, 10, 15, 22, 31, 35, 41]

◯セレクション
配列をソートしてN番目の値を取ってくるという処理。
ソートしてもいいけど、1回しか呼ばれないとか、適宜順番が変わるような配列だとセレクションがおすすめ。

公知のセレクションアルゴリズムがあって、その中でいくつかを並列化する。

1. 配列数がQ(本では5を勧めている)より小さければデータをソートして、k番目の要素を返す。Qより多ければ次のステップへ
2. チャンクから中央値を選ぶ(本では配列を分割して中央値を求め、その中からさらに中央値を求めるやり方をしているけど、配列の中身が適度にバラバラなら適当に選んでもいいかも)
3. データを A.中央値より小さい値を持つ B.中央値と同じ値である C.中央値より大きい値を持つ の3種類に分け、A,B,Cの数を数える。
4. 求めるk番目の要素がどこに入るかを調べる。Bに入るなら値を返して終了、AかCなら再帰的に1から処理を続ける。

本で高速化しているのはこのうちの2の処理、3の処理、4の処理の一部である。ポイントは4の処理で、再帰的に呼び出す際の配列の部分集合を使うのにプリフィックススキャンを使って詰め直し先のインデックス値を求めている。逐次処理に慣れきっていると重そうだけど、実際実行してみたら早いのかな? 要検証。

並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング
Clay Breshears
オライリージャパン
売り上げランキング: 8422

情熱プログラマー ソフトウェア開発者の幸せな生き方

4月 15th, 2010 by tune 2 comments »
情熱プログラマー ソフトウェア開発者の幸せな生き方
Chad Fowler
オーム社
売り上げランキング: 12001

ソフトウェア開発者のみならず、あらゆる分野でその道を極めようとしている人におすすめです。プログラマ固有のところは極めて少なく、自分の人生を自分で切り開いていくために必要な情報が分かりやすく整理されています。

以下この本で気になった所を引用しておきます。この本がプログラマ以外の人にも示唆に富む内容であることが伝わるのではないかと。

より良い製品を作って仕事を確保することだけが大切なのではない。より実りある人生を送るためのスキルと感性を磨くことも大切だ。人生には素晴らしいことがたくさんある。仕事はそのひとつに過ぎない。(David Heinemeier Hansson)

偉大になることを望んでいる人のほうが、自分の仕事をこなせれば良いと思っている人よりも、偉大になる可能性がずっと高いからだ。

何かのスペシャリストであると言うことを、単に他のことを知らないという意味で使っている人が多すぎる。

ビジネスの仕組みを知りもしないで、ビジネスが利益を上げるために想像力を働かせて協力できるだろうか?
・・・
想像力を働かせて付加価値を高めるためには、自分が関わるビジネスについての徹底的な理解が必要だ。

本当の意味で何かを習得しようと思ったら、誰かに教えてみることをおすすめする。自分の理解をはっきりした形にする一番いい方法は、自分の言葉を使って、他の人にもわかるように説明することだ。

プロセスを身につけたいなら実践しろ。

いいマネージャの役割は、チームの仕事に優先順位を設定し、チームが仕事をこなすために必要なものを用意し、チームがやる気と生産性を維持出来るように配慮し、最終的に要求を実現することにある。

短く働いた方が、より多くの成果をあげられる。

ソフトウェアの品質が本当の意味で試されるのは、何か問題が起きた時だ。

本当に出来ないときに臆せずに「できません」と言える強さを持ったチームメンバーがいれば、彼らの「できます」という言葉には偽りが無いと確信出来る。

多くのソフトウェア開発者は勘違いしている。事情に通じたマネージャや雇い主なら自分の技能を見ぬいて当然だと思い込んでいるんだ。・・・全部言い訳。彼らは怖がっているだけさ。
誰かが何かすごいことをしても誰もそれを知らなければ何もなかったのと同じだって言うんだ。

大局的に見るなら、作文技術は必要かつ供給不足なんだ。
君ももっと大量の文章を書くことになる。文章を書くことが仕事の一部になるとすれば、もっと作文技術を磨いた方がいい。

君に信念がないと、こういうことはできない。会社の連中が間違った事をするのを傍観していられない。改善の余地があるなら君が変えなければ。

目立つっていうのは、聞かれる前からみんなが君のことを話題にするっていう意味なんだ。

君のキャリアにとって本当に重要なのは昇進でも昇給でも無い。重要なのは、そういう成果を得るために努力した時間だ。もっと重要なのは、そういう成果とは関係ないところで努力した時間だ。

並行コンピューティング技法 第4章 & 第5章

4月 11th, 2010 by tune No comments »

短いので今週は2章分まとめて読みました。

◯第4章 マルチスレッドアプリケーション設計の8つのルール
・8つのルール

  1. スレッド化設計モデルに加えるべきルール、順不同。
  2. 真に独立した処理を特定する
  3. 並行性はより上位で実装する
  4. コア数増加に備えスケーラビリティ対応を早期に計画する
  5. スレッドセーフなライブラリを使用する
  6. 適切なスレッドモデルを採用する
  7. 実行順序を前提としない
  8. ローカル変数を使用する、できなければロックで保護する
  9. 並行性向上のためのアルゴリズム変更を恐れない

・ルール1: 真に独立した処理を特定する
これが最も重要。 処理が互いに独立していなければ並行実行できない。

・ルール2: 並行性はより上位で実装する
並行性を見つける方法は2種類ある。

  • ボトムアップ
  • トップダウン

どちらを選ぶにせよ、より上位で並行化した方が良い。 アルゴリズムの上位レイヤほど、より多くの独立した処理を含んでいるからである。

・ルール3: コア数増加に備えスケーラビリティ対応を早期に計画する
今後もプロセッサコア数は増加の一途であることが予想される。 開発中のソフトウェアであっても、このことは考慮に入れておくべき。

並行性の設計はタスク分解とデータ分解の2種類があったが、 アプリケーション内の独立した処理とデータサイズではデータサイズの方が増える傾向が強いため、 データ分解設計の方がスケーラビリティーでは有利である。

設計中のソフトウェア/システムが計画している処理能力を十分に達成できても、 将来要求される処理能力は増加する可能性が高い。 処理能力に余裕があれば、処理するデータはまだ誰かが持っている。

・ルール4: スレッドセーフなライブラリを使用する
車輪の再発明は決していい方法ではない。 一般的なライブラリ関数で置換可能であればそれを使うこと。

使用の際には、マニュアルを参照してライブラリがスレッドセーフであるかを必ず確認する。 自作ライブラリなら関数がリエントラントであるように設計する。

・ルール5: 適切なスレッドモデルを採用する
スレッドの明示的な使用(Pthread/Windowsスレッドの直接的な利用)は避けるべき。 抽象化ライブラリ(OpenMP/Intel Threading Building Blocks)を通してスレッドを利用すること。 多くの並行化作業はスレッドを明示的に操作する必要があるほど柔軟性が求められておらず、 実装が複雑になるとバグが入る可能性が高くなる。

開発上の規約などにより、抽象化ライブラリの使用が禁止されている場合でも、 プロトタイプは抽象化ライブラリを使うことで手間を省くことが出来る。

・ルール6: 実行順序を前提としない
スレッドの実行はOSなどのスケジューラで管理されるものであり、 アプリケーション側で順序を決定することは出来ない(非決定性がある)。 スレッドがどんな順序で実行されても正しい結果を返すように設計すること。

また性能の観点から、出来る限りスレッドの実行に制約を課すべきではない。 例えばスレッド処理の待ち合わせをするときは本当に必要か立ち止まって考える必要がある。

・ルール7: ローカル変数を使用する、できなければロックで保護する
同期処理は必要悪だが、最小限の使用に留める必要がある。 共有変数の更新が少ないほど、オーバーヘッドも少なく済む。

まずはスレッドごとに持たせるローカル変数で問題が解決出来ないかを考える。 駄目なら適切なロックを共有データに対して適用する。 デッドロックの温床となるため、1データに対して複数のロックを対応付けてはならない。

・ルール8: 並行性向上のためのアルゴリズム変更を恐れない
逐次処理では最良だったアルゴリズムが、並行処理では最良でないことがある。 並行化出来なかったり、他のアルゴリズムの方が並行化による恩恵を受けやすいことがある。

◯第5章 スレッドライブラリ
・抽象化ライブラリ
スレッドの制御(作成・管理・同期)を抽象化し、プログラマに楽をさせてくれるライブラリ。 スレッドを明示的に作成する処理は無く、柔軟性は落ちる。

・OpenMP
専用のpragma、指示文(ディレクティブ)、環境変数を用いて並行処理可能な部分を指定する。 並行実行コードはコンパイラにより生成される。 並列環境と非並列環境でほぼ同一のソースコードを使用できるという利点がある。

スレッドの管理はfork-joinモデルを採用している。 マスタスレッドが並行処理可能な領域(パラレルリージョン)に到達すると、子スレッドが生成され(fork)、 各スレッドがパラレルリージョンを実行する。 パラレルリージョンの終了時には子スレッドが待ち合わせ(join)、 パラレルリージョン後からメインスレッドが処理を続行する。

・Intelスレッディング・ビルディング・ブロック
並列アルゴリズムが定義、実装、提供されており、 並行処理がカプセル化されたクラスを通して使用する。 商用バージョンとオープンソースバージョンがある。

・明示的スレッドライブラリ
PthreadとWindowsスレッドがある。提供される関数は大差ないはず、必要に応じて調べて使いましょう。

並行コンピューティング技法 ―実践マルチコア/マルチスレッドプログラミング
Clay Breshears
オライリージャパン
売り上げランキング: 18712

麻雀問題解いてみた

4月 4th, 2010 by tune 1 comment »

Mahjong set [04/04]
Creative Commons License photo credit: drdaeman

makeplex salon:あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 (1/2) – ITmedia エンタープライズを解いてみました。ソースはtune’s itmedia_makeplex at master – GitHubに上げてありますのでリビジョンも見れるようになってます。最初のコミットを上げるまでに、面子の表示順の違いを抑えるところで詰まってチンイツの待ちを出力するプログラム – 107143955443560を参考にしました。参考にしましたというよりもC++のソースをRubyに移植しましたと言う方が近いほど同じ処理です。基本的なアルゴリズムは最後まで踏襲しています。

最初のコミットまでが3時間ぐらい、リファクタリングに1時間ぐらいです。ちょっと時間がかかりすぎですが、日常的に書いてないRubyで、日常的にプログラムしてない家のMacパソコン、プラグインが古いのか5分に1回落ちてしまうMacVimで時間がとられたと言い訳しておきます。ただの実力不足です、ごめんなさい。

成立する可能性がある面子を減らしながら、総当たりで探索しています。面子の順序違いによる重複表示を避けるのが結構面倒ですね。刻子を優先して探さなければならず、色々試行錯誤してみたのですが、参考にさせていただいたid:staebchenさんよりも良さそうな方法に達しませんでした。もっといいやり方があると思いますが、参考まで。

#!/usr/bin/ruby

class Array
  def sum
    s = 0
    self.each do |v|
      s += v
    end
    return s
  end
end

class Fixnum
  # 刻子
  def anko
    num = self+1
    "(#{num},#{num},#{num})"
  end

  # 順子
  def shuntsu
    num = self+1
    "(#{num},#{num+1},#{num+2})"
  end

  # アタマ
  def atama
    num = self+1
    "(#{num},#{num})"
  end

  # 単騎
  def tanki
    num = self+1
    "[#{num}]"
  end

  # リャンメン(ペンチャンも兼ねる)
  def ryanmen
    num = self+1
    "[#{num},#{num+1}]"
  end

  # カンチャン
  def kanchan
    num = self+1
    "[#{num},#{num+2}]"
  end

  # シャボ
  def shabo
    num = self+1
    "[#{num},#{num}]"
  end
end

#
# 雀牌を表す数字列を解析し、0〜8の配列に与えられた個数を入れて返す
#
def parsePai(str)
  pai = Array.new(9, 0)
  str.split(//).each do |p|
    pai[p.to_i-1] += 1
  end

  # 入力の妥当性チェック
  if pai.sum != 13 then
    # 与えられる牌は13枚
    raise RuntimeError
  else
    pai.each do |val|
      if val > 4 then
        # 1種類の牌が4枚より多いことはない
        raise RuntimeError
      end
    end
  end

  return pai
end

#
# 手牌を再帰的に解析し待ちを表示する
#
# 順子を刻子に優先して探索する。
# 順子はfromが9〜18の時に探索される
#
def analyzeTehai(pai, from=0, mentsu=[])
  shuntsu_phase = 9
  skip_anko_check = false

  if from >= 9 then
    skip_anko_check = true
    from -= shuntsu_phase
  end

  if pai.sum > 4 then
    # 面子を揃える

    # 刻子
    unless skip_anko_check then
      from.upto(8).each do |i|
        if pai[i] >= 3 then
          tmp = pai.dup
          tmp[i] -= 3
          analyzeTehai(tmp, i+1, mentsu+[i.anko])
        end
      end
    end

    # 順子
    from.upto(6).each do |i|
      if pai[i]>=1 && pai[i+1]>=1 && pai[i+2]>=1 then
        tmp = pai.dup
        tmp[i] -= 1
        tmp[i+1] -= 1
        tmp[i+2] -= 1
        analyzeTehai(tmp, i+shuntsu_phase, mentsu+[i.shuntsu])
      end
    end

  else
    # 残った4枚から待ちを絞る

    # アタマを探す
    0.upto(8).each do |i|
      if pai[i] >= 2 then
        tmp = pai.dup
        tmp[i] -= 2
        analyzeMachi(tmp, mentsu+[i.atama])
      end
    end

    # 面子(刻子 or 順子)があれば単騎待ち
    # 刻子
    unless skip_anko_check then
      from.upto(8).each do |i|
        if pai[i] >= 3 then
          tmp = pai.dup
          tmp[i] -= 3
          analyzeTanki(tmp, mentsu+[i.anko])
        end
      end
    end

    # 順子
    from.upto(6).each do |i|
      if pai[i]>=1 && pai[i+1]>=1 && pai[i+2]>=1 then
        tmp = pai.dup
        tmp[i] -= 1
        tmp[i+1] -= 1
        tmp[i+2] -= 1
        analyzeTanki(tmp, mentsu + [i.shuntsu])
      end
    end
  end
end

#
# 4枚から待ちを絞る
#
def analyzeMachi(pai, mentsu)
  0.upto(8).each do |i|
    # リャンメン(ペンチャン)
    if pai[i]==1 && pai[i+1]==1 then
      puts mentsu.sort.to_s + i.ryanmen
    end

    # カンチャン
    if pai[i]==1 && pai[i+2]==1 then
      puts mentsu.sort.to_s + i.kanchan
    end

    # シャボ
    if pai[i]==2 then
      puts mentsu.sort.to_s + i.shabo
    end
  end
end

#
# 単騎待ちの数字を調べて待ちを表示する
#
def analyzeTanki(pai, mentsu)
  # 単騎待ち
  0.upto(8).each do |i|
    if pai[i] == 1 then
      puts mentsu.sort.to_s + i.tanki
    end
  end
end

# 以下実際の処理
pai = parsePai ARGV[0] unless ARGV[0] == nil
analyzeTehai(pai)
Pages: Prev 1 2 3 4 5 6 7 8 9 10 ...246 247 248 Next