ページ

2011年12月27日

今年一年間とか


年の瀬なので、今年一年間を3分で振り返ります。今年は何かいろいろ会ったような気がします。

一月は平凡な年の幕開けだったのか、その後いろいろありすぎたせいか、あまり印象にありません。2月は健康診断がありました。これが、今年前半のいろいろの始まりでした。膵臓に腫瘍があるって言われて病院に行くと腫瘍があるのは膵臓じゃないよ〜、と。で、しばらくして検査入院するんですが、それが3月の震災の翌週でした。通勤が大変だ! 計画停電だ! って騒いでいるときに、病院でのんびりしていました。4月を飛ばして5月に手術しました。それは、ブログにおもしろげに書いたので、手術が終わっても笑ったと言われても、誰も心配してくれないという、喜劇のような現実を目の当たりにしました。手術すると健康について考えるようになるって聞いた気がしますが、それは僕には当てはまらなかったようです。6月は、震災の経済的な影響は大きかった、と。

さて、後半です。後半は、前半ほどは何もありませんでした。夏は、今年は、初めて子供を近所のプールに連れて行きました。今まではお金がかからないので海に連れて行っていましたが、今年はプールです。何故って? 放射線を気にしたわけじゃないです。砂が熱かったからです。秋から冬にかけて朝組のせいでだんだん朝が早くなりました。でも、クリスマスでもとの生活に戻ってしまった僕は、来年も早起きできるか心配です。 

それでは、来年は? なるようになるんでないかな?





2011年12月24日

猛獣がやってきた

猛獣を飼うことになりました。

IMG_0041.jpg 

生後二ヶ月になるベンガルネコです。ヒョウのような模様が特徴のネコです。先祖はヤマネコです。そのため、優れた運動性能らしいです。2m近くジャンプするネコもいるらしいです。今日、やって来ました。まだ、新しい環境に慣れていないようで、マガジンラックと壁の5cmぐらいの隙間に隠れています。

こやつ、どれぐらい猛獣かというと、肩の上にのって主人の口を食べようとします。それだけじゃなく、主人のにおいをかいで、いつ食べようか考えているようでした。恐ろしや。

僕の子供の頃もいろいろ動物を飼っていたので、子供の教育上いいんじゃないか?と言う名目ですが、単純に僕が飼いたかったらですね。 

プログラマが飼うネコは、ガジェットに興味があるのかもしれません。iPhoneをしげしげと見て、「これ、食える?」って感じでにおいをかいでいました。そして、タッチして操作しようとします。そのうち、勝手にiMacを操作しそうで、怖いです。僕の代わりにコードを書いてくれるかもしれませんね。

 

でわでわ 



2011年12月23日

これがバーガーキングのピザサイズバーガーだった

会社の同僚たちがランチをどこで食べようか?っていう話題で盛りあがっていました。まあ、僕が発端だったのかもしれません。それで、最初は巨大餃子を食べに行こうと言うことになったのですが、残念ながら巨大餃子は夜のメニューでランチではやっていません。巨大料理にとりつかれてしまった男たちは、次の白羽の矢がたったのがバーガーキングのピザサイズバーガーです。ピザサイズバーガーは期間限定のメニューでたぶん、明日か明後日ぐらいまでです。

まずは、男4人が六本木のバーガーキングに突撃です。時間は午後一時にオフィスを旅立ち、店舗に向かいます。店舗によって数両限定なので、最悪売れ切れすらあり得ます。男たちは冷静を装いつつ、心臓の鼓動は速くなっていました。 

店舗につくと、いわががさんがきれいなおねーさん店員に「ピザサイズバーガー一つ」と男らしく注文します。 店員の選択からもう、抜け目がありません。自然と期待が膨らみます。今日はピザサイズバーガーを食べるために男たちは集まりました。サイドメニューなんかでバーガーを楽しみがそがれるのは得策ではありません。おのおのドリンクを注文して、バーガーができあがるのを席で待ちます。

IMG_0035.jpg 5分ほどでバーガーが運ばれてきました。ピザサイズだけあって、ピザを連想する入れ物に入って出てきました。この演出に男たちの期待は最高に高まります。期待にさらに胸を膨らませながら、開封の儀を行います。

IMG_0037.jpgそして、その全貌があらわになります。 比較のために置いてあるドリンクはLサイズです。ドリンクがとても小さく見えます。

バーガーはすでに4等分された状態で入っています。肉は・・・。巨大な一枚の肉の塊を期待していたのですが、普通サイズのハンバーグが4つのっているだけでした。これは少し残念感が漂います。しかし、巨大なハンバーグを作る機械がないのでしょう。これは仕方ないですね。

写真撮影会も終わって試食です。男たちはおのおのバーガーをもって食べ始めます。はっきり言って、食べにくいです。さらに、お皿がないのでひたすら食べ続けるしかありません。袋もないので、油断するとレタスなどが下に落ちます。一心不乱に食べ続けます。その時間、およそ3分。食べ尽くしました。黙々と食べ尽くしました。食べている間、誰もしゃべろうとはしません。それは男たちの戦いが熾烈を極めたことを意味します。一気に食べ尽くすと、一瞬の達成感の後に、むなしさが漂います。短期決戦だったためによりむなしさがつのります。

このむなしさを解決するには、もう、あれしかありません。むなしさを残しつつ店を経ちます。しかし、オフィスにもどる男たちには、出陣のときになかったものが手にされています。男たちは、オフィスでの第2戦のために、さらなるピザサイズバーガーを手にしていたのです。

もしも店員さんがTwitterをやっていて、この光景をtweetしていたら

「ピザサイズバーガー キタ━━━」

「店の中でぼろぼろこぼしながら黙々と食っているよ」 

「帰りにもう一個ピザサイズバーバー買って帰ったよ、プッ」

って感じになるはず。

 

さあ、明日は休みだし、早く食べに行ってください

 

でわでわ 

 

 

 



2011年12月22日

おこづかい制にしてみた

無駄遣いは全然していないんですが、一月にどれくらいお金を使っているかちゃんとは把握していなかったので、数ヶ月前からおこづかい制にしてみました。と言っても、嫁から「おこづかいよ」って貰うわけじゃなく、給料日に、自分でおこづかいと決めた額をおろして、次の給料日まではATMに近づかない、って言うだけです。朝組で訓練されているので、自律の精神のもと、他のヒト(嫁)に強制されなくても守ることができます。

このページによると、 30代、40代の人たちのお小遣いは4万円台です。思ったより沢山貰っています。漠然と流れ去るニュースを眺めていると3万円ぐらいだと思っていたので、それよりは多いです。他の会社に移った昔の同僚はかなりおこづかいが少なかったようですが、本当の実体は分かりません。

とりあえず、僕が勝手に想像するサラリーマンの平均おこづかいは、35000円なので、とりあえず、それにしています。それで困ることもないし、むしろ少し余るので、もともとほとんど現金を使わなかったのかもしれません。

クレジットカードのことは聞かないでください。 



2011年12月21日

とある開発の風景

これは、アドベントカレンダーとは一切関係ありません。では、アリエルじゃどんな風に開発しているのか、ってお話です。開発と言ってもプログラマに限ったお話です。めんどいのでプログラマによる機能の追加とバグの修正を開発って書きます。

開発は基本的にすべてチケットを通して行います。チケットの粒度は様々です。大きな粒度のチケットはプログラマの判断で細分化されて行きます。大元になるチケットは、プロジェクトの開始の時に偉いヒトによって各プログラマに割り振られます。開発者によってある程度の持ち場が決まっているので、割り振られるときはその持ち場と今後の進んでいって欲しい方向とスキルによって分けられます。偉いヒトがざっとした工数見積もりも済ませているので、プロジェクトの工数があふれない程度の量です。

バグ修正的なチケットは、バグを直せばいいだけです。大きな機能追加は全く違った開発プロセスを歩むので、ここでは書きません。適切な粒度の機能追加的なチケットは、大まかな方向性は決まっていますが、詳細は決まっていません。基本は担当開発者がまず、外部仕様策定から始めます。仕様は、チケットをあげたヒトやプロジェクトマネージャ、プロダクトマネージャと相談しながら決まっていきます。プロダクトマネージャがこうしたいと思っても、表向きは担当開発者が決める形になっています。ただ、あまりにも紛糾していて物事が進まないときは、偉いヒトの強権が発動されます。

機能の合意が取れると開発が始まります。プロジェクトの開始の時に、大体の締め切りを決めてそれにむけて開発を行います。2点見積もり(だっけ?)にした方がいいと僕は思うのですが、プロジェクトマネージャがうんといわないので、その締め切りに間に合うように開発します。

開発中の質疑応答などはほぼチケットを通して行われるので、ログとして機能します。実装が終わると単体テストを開発者が行って問題ないと、コードレビューが行われます。これは、大体横にいる人にやって貰います。コードレビューを通さずにコミットするヒトもいますが・・・。レビューが通ればコミットします。

コミットするとJenkinsさんとか自動テストととか、いろいろチェックされます。問題があるとチケットは差し戻されます。それ以外にも、大量のコミットをピンポイントで眺めている変人がいて、変なモノをコミットするとチケットが差し戻されたり、勝手に修正されたりします。怖いですね。 

それからドキュメントがチケットに書かれます。 レビューや実装前にドキュメントを書くヒトもいますが、それは人それぞれです。書かないといけない内容は、リリースノートに書く機能の説明とそれに付随する情報、テスターさんがテストするための情報とさらに詳細にテストした方がいいところ、実装方法のまとめとか、バグであればその原因とか。

そして、チケットが閉じられるとテスターさんが再度いろいろテストします。開発者とテスターさんの境界線上のことはいいたいこともありますが、それは別の機会に。テスターさんがテストを行って問題があると差し戻されてまた、修正します。テストがクリアすると、ドキュメントに不備がないかチェックされ、それが終わると本当の終了となります。ふー。

至って普通でおもしろみがないですね。 

 



2011年12月16日

アリエルの朝の変遷

こんにちは、アリエル1の女性好きの大谷です。ウソです。僕は至って普通の紳士です。キリッ。しかも、女子供が飲むようなお酒しか飲まない軟弱モノです。そんな僕でもアリエルにいることを許してください。ごめんなさい。ごめんなさい。

と言うことでsodexからAriel Advent Calendarのバトンが回ってきました。これはそのエントリです。おそらくこれが、僕の最後のAdvent Calendarになると思います。Python3のエントリpypyのエントリをすでに書いています。Python3の方がよく読まれているらしいです。pypyの方は手を抜きすぎたせいかもしれません。いや、しょーまたんのpypyのプレゼンを聞いていて、rpythonでフィボナッチ数列の計算をやれば、楽にエントリが書けると思っていたら渋川さんに先を越されたので、ネタが・・・。

さて、 本題です。今は朝組の組長がアリエルの朝を支配していますが、アリエルの朝ってどんな感じだったのでしょうか?勤務時間とかお話を交えて振り返ってみましょう。

時はさかのぼること十年ほど前、2000年にアリエルができました。僕が働き始めたのは7月からです。僕が外人らしきヒトと道ばたで「It's your fault」とか言い合ってから一ヶ月後のことです。あの頃は若かった。 入ったときはオフィスはないので、勤務時間はありません。子供を保育園に追いやってから夜に迎えに行くまでが働いていた時間です。それから、いろいろやって夜の9時か10時ぐらいから仕事の第2部がはじまります。CTOにはあのころは朝はなかったと思います。 

それからオフィスができます。最初はまだ勤務時間がなかったと思います。オフィスができてもすぐには通勤しなかったような気が・・・。派遣のヒトとか、新しい人が入ってきて仕方なく会社に行くようになりました。そして、新しい人が入ってくると勤務時間もちゃんとしなくてはいけないので、何も考えずにロータスのコアタイムをそのまま使って11時開始になりました。でも、この頃はコアタイムはありますが、遅刻してもペナルティはありません。めんどいので誰もチェック付けていません。多分、有給休暇も正確に何日休んだかなんて記録をとっていなかったかもしれません。まだ、牧歌的な時代のお話です。そのころはみんな11時間際にやってきていました。10時頃はオフィスは真っ暗です。

さて、そんな時代も長くは続きません。CTOが大量のお金を浪費しつつ、製品は売れません。売れないといろいろなところにしわ寄せが行きます。売れない原因はいろいろ考えらますが、一部の人たちの間では開発の勤務態勢とか、だらしなさが売れない原因だとささやかれたりします。まあ、言いがかりもいいところですね。そんな感じでコアタイムが1時間早くなって10時からになりました。でも、そんなの納得できる理由じゃないですね。なので、みんな守らなかった・・・、じゃなく、11時になれた体は10時には適応できなかったのです。それで、僕は10時30分ぐらいに来ていました。この頃も大きな罰則はないです。なので、誰も守らない10時からのコアタイムはなし崩し的に11時に戻りました。大衆の勝利の瞬間です。このころもまだ、牧歌的な名残があります。

それから、買収とか2006年ぐらいから会社の成長とかがあります。買収はどうでもいいのですが、会社が大きくなり始めると牧歌的な運営では会社の秩序が崩壊します。最初のメンバーのように一日十数時間働くのが当たり前の人たちばかりじゃなくなります。そういうこともあって、今までのいい加減な体質じゃダメだと言うことで、11時に少しでも遅れてたら遅刻としてカウントするようになりました。でも、このころには僕は10時ぐらいに会社に来るようになっていました。

そして、2011年秋、アリエルの朝のインフレが起こり、朝組が誕生しました。アリエルの朝は、自律の精神のもと、7時から自発的に働き始める異端の集団の誕生です。アリエルは自律をむねとし、日夜修行に励むのです。

次は、アリエルの天才ハッカーのm2yaさんです。おそらくCTO以上の大物です。

でわでわ 



2011年12月15日

朝組の危機

アリエルには朝組という秘密結社があります。以前書きましたがアリエルの開発の朝はとっても早いのです。朝組は8時までに出社することを命題に@t2y が中心となって結成されました。@t2y 組長の7時の出社から朝組の一日は始まります。朝組の主要メンバーは現在4人です。組長はもっと勢力を拡大したいようですが、なかなか難しいようです。CTOを朝組に引きづりこもうとしていますが、生活のスタイルを変えるのは大変なようです。

さて、朝組にとって今はとてもつらい季節です。@kawanoshinobu は寒さのあまり、朝組に遅刻してきます。遅刻するたびに@t2y に謝っています。朝組は強権体制なのです。おそらく・・・。一度入ると、朝組を抜けることはできないという噂もあります。

僕も起きるのがつらいです。「あと1時間布団の中にいてもいいよ」と悪魔のささやきが毎朝聞こえます。しかし、ここで2度寝してしまうと、組長のおしかりが怖いので、がんばって起きて出社します。多分、年内は大丈夫だと思いますが、正月休み明けが心が折れそうで、怖いです。おしかりがなくても、朝組は自分で自分を律するという心構えがあります。修行の道は険しいのです。

でも、朝早くから活動し始めると一日がとても長く感じられるので、それはとてもいいです。

 

でわでわ 



2011年12月13日

pypyのスレッドとかgreenletとか何か

pypy advent calendarのエントリです。ごめんなさい。ネコを飼うのでそのことに関心が向いて、pypyのこと、すっかり忘れていました。なので、いつにも増して、とってもうすーいエントリをだらだらと書きます。pypy闇の軍団長兼会長様、許してください。

まずは、昔のフィボナッチ数列の計算するコードを持ち出します。
import time

def fibonacci(n):
    value = 0
    f1 = 1
    f2 = -1
    for i in range(n+1):
        value = f1 + f2
        f2 = f1
        f1 = value
    
    return value

if __name__ == "__main__":
    for x in range(3):
        fibonacci(3)
    time.sleep(0)
    start = time.time()
    for x in range(4000, 5000):
        fibonacci(x)
    end = time.time()
    print end - start

これを実行すると、僕のMacBook Airだと今日は大体1.11秒です。Java(Jython?)などのちゃんとしたスレッドを持ってる人たちは、ループの中をスレッドにするともっと高速になるんじゃないか?って考えます。なので、スレッドにしちゃいましょう。
import time
import threading

def fibonacci(n):
    value = 0
    f1 = 1
    f2 = -1
    for i in range(n+1):
        value = f1 + f2
        f2 = f1
        f1 = value
    
    return value

if __name__ == "__main__":
    for x in range(3):
        fibonacci(3)
    time.sleep(0)
    thread_list = []
    start = time.time()
    for x in range(4000, 5000):
        thrd = threading.Thread(target=fibonacci, args=(x,))
        thread_list.append(thrd)
        thrd.start()
    for thrd in thread_list:
        thrd.join()
    end = time.time()
    print end - start

さて、これを実行すると1.7秒ぐらいです。参考までにCPythonで実行すると2.01秒でした。さらに参考までにPython3で実行すると2.37秒でした。Python3ダメダメじゃん。
(;゜〇゜)はっ!これはPython3のエントリじゃないからこれ以上Python3のことを書いたら団長に怒られる!
さて、スレッドにした方が遅いですね。まあ、何も不思議じゃなくって、GILとかあるので、想定の範囲内です。ちなみに、1000個スレッドがあると、LinuxやMacはメモリは見かけ上8Gぐらいなります。まあ、単純な計算だけならスレッドにするより何も考えずにシーケンシャルに行った方が良いと言うことですね。もしくはプロセスのフォークで・・・。でも、途中でネットワークとかブロックするような処理があると、シーケンシャルにやると遅くなっちゃいます。

ここまでが前置きです。結論はないです。Application-level Stackless featuresにcontinuletとgreenletについて書かれています。どっちもマイクロスレッドですね。continuletのレイヤの上にgreenletと同じAPIのモジュールを実装しているようです。32bit環境ではスレッドあたり4KBのメモリ使用量だって書いています。本物のスレッドに比べると遙かに少ないです。
と言うことで、こんなコードを書いてみました。
import time
from greenlet import greenlet

def fibonacci(n):
    value = 0
    f1 = 1
    f2 = -1
    for i in range(n+1):
        value = f1 + f2
        f2 = f1
        f1 = value

    return value

if __name__ == "__main__":
    parent = greenlet()
    start = time.time()
    grs = [greenlet(fibonacci, parent) for _ in range(1000)]
    i = 4000
    for gr in grs:
        gr.switch(i)
        i += 1
    end = time.time()
    print end - start
実行すると1.2秒ぐらいです。最初のコードが1.1秒ぐらいなので0.1秒ぐらいのオーバーヘッドですね。まあ、待ちがないマイクロスレッドでスレッドの途中でコンテキストの切り替えがないので、つまんないですね。

ちょっとこれはいろいろやり過ぎているので、もっと単純なコードでやってみましょう。
import threading
import time


def test2():
    pass

start = time.time()
thrds = [threading.Thread(target=test2) for i in range(1000)]
for thrd in thrds:
    thrd.start()
for thrd in thrds:
    thrd.join()
end = time.time()

print end - start

単にスレッドを作って空の関数を実行しているだけです。これだけのコードで0.29秒です。感想としては、遅い・・・。CPython2.7だと0.14秒です。うっ、pypy負けてる。と言うかJITがうまく動かなさそうなコードなのでいいです。ちなみにPython3でも0.14秒ぐらいでした。
それではgreenletで。
from greenlet import greenlet
import time

def test1(x, y):
    for gr in grs:
        z = gr.switch(2)

def test2(u):
    #print id(greenlet.getcurrent())
    gr1.switch(42)

start = time.time()
gr1 = greenlet(test1)
grs = [greenlet(test2) for x in range(1000)]
gr1.switch(1, 2)
end = time.time()

print end - start

このヒトを実行すると0.07秒です。スレッド重いですね。

2011年12月12日

年末は今年を振り返るモノらしいけど・・・

だらだらと、いろいろ見たり調べたり横道にそれたりしていると、このブログを書き始めて5年が経過していることに気づいてしまいました。早いものです。年末は今年を振り替えったりするモノですが、5年前を振り替えって見ます。

5年前はアリエルはまだ中目黒にいました。このブログを書き始めた頃はまだ、毎月順調に CTOがまだ、資金を浪費していた 赤字を垂れ流していた時期です。それでも、書き始めた半年前、僕が潜行して行っていた調査期間とかを含めると1年前から新しいプロジェクト、と言うか現行の製品を作っていたときです。あの時はまだ、狂気の中でした。ダメだといっていたのにCTOが勝手にリリースを3ヶ月早めちゃうし・・・。

その後、紆余曲折があってその製品はとりあえず会社を黒字にしてくれたし、まあ、数億、と言うかそれ以上の売り上げがあるようになりました。まあ、不思議です。でも、成功したか?って言われると、うーん、この程度の売り上げじゃ失敗じゃなかった、って言う程度ですね。 二番目につまらないパターンかもしれません。一番つまらないパターンじゃないです。

まあ、5年前はそんな感じです。5年前の狂気が終わると、僕も30代後半になっていました。中目黒にいた最後の辺りぐらいにテストチームを作りました。作るの、大変だったんですよ。CTOは頑固者なので・・・。テストチームを作ったのはどうでもいい話ですが、その頃から僕が丸くなったって誰かが言っていました。僕は昔から優しいんですがね。アリエルではCTOが一番怖いですよ。

それからは、まあ、いろいろありましたが、本当に大変だったのは中目黒にいたころまでだったと思います。それ以降もいろいろありましたが、まあ、中目黒にいたころに比べたらそれほどでもないです。多分、多少の失敗が許されるか、許されないかの違いかもしれません。

過去は美化されるのでどこまでが本当かは不明です。でも、今でも十分楽しいですけどね。



2011年12月9日

Python3のconcurrentパッケージ

こんな経緯Python Advent Calendarに参加させられてしまいました。まずは、言い訳から。僕がPython3を触ったことがあるのは2,3年前で、それも数日だけです。それ以降全く触っていません。はい。Python3初心者です。笑いたければ笑ってください。そんな僕がPython3で何を書こうか、と言うことで、あのみんなが大好きなJavaからぱくったと名高いconcurrentパッケージについて書きます。
まず、まっとうなPythonプログラマならあのレガシーなJavaぐらい分かるよね。Javaが分かるんだったらJavaのjava.util.concurrentパッケージぐらいは知っていて、concurrentて常識だよね、と言うことで、concurrentについての説明は多分、省略です。

PythonのconcurrentパッケージはJavaのconcurrentパッケージのほんの一部です。って言うか、executer関連しかないじゃん・・・。concurrentパッケージの下にはfuturesしかいないし・・・。でも、今後増えそうな感じがして頼もしくはあります。Python3でGILがどうなっているか知りませんが、pypyやjythonなどもあるので、スレッド周りの安全性を実装系に依存しちゃうのはあまりうれしくありません。なので、スレッドの安全性は意識した方が良いと思うわけです。でも、そんな能書きはいいのでゆっくりとコードと戯れてみましょう。

まずは、concurrentを使わないコードです。もっと最初はスレッドを使わないモノが必要ですが、めんどいのでごめんなさい。
import threading
import time

def thread_func():
    ident = threading.currentThread().ident
    print("start")
    for i in range(4):
        print("waiting " + str(i))
        print("current thread: " + str(ident))
        time.sleep(0)
    print("done")

l = [threading.Thread(target = thread_func) for i in range(4)]
for thrd in l:
    thrd.start()
for thrd in l:
    thrd.join()

スレッドをぐるぐる回して、最後にjoinしてすべてのスレッドが終わるのを待っています。これを実行するとスレッドが切り替わっているのが分かります。ループ内でちょっと重い処理をして、お互いに依存関係がないときに、こんな感じのコードは便利です。

でも、今回はスレッドというかループ数が4だから良いけど、もっと多いと一瞬で破綻しちゃうかもしれません。LinuxとかMacはデフォルトのままだとスレッド一つにつきメモリを8M消費します。こんなところで大量にメモリを消費すると困っちゃいます。と言うことで、大体スレッドプールとかを実装するわけです。まあ、みんな同じことを考えます。と言うことでDRYって怒られそうです。怒られてしょぼくれているあなたにconcurrent.futuresのexecuterです。まずは、ThreadPoolExecuterです。名前からしてそれっぽいでしょ。実行して貰えれば、スレッドが最大二つ(max_worker=2)しか動かないです。そして、別のスレッドで動いているのが分かると思います。でも、workerが一つしかいないよ!って言う人は、もっと沢山submitしてあげれば大丈夫です。

import threading
import concurrent.futures
import time

def executer_func():
    ident = threading.currentThread().ident
    print("start")
    for i in range(4):
        print("waiting " + str(i))
        print("current thread: " + str(ident))
        time.sleep(0)
    print("done")
    return ident


with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executer:
    l = [executer.submit(executer_func) for i in range(4)]
    for future in l:
        print("=== result: " + str(future.result()))

ThreadPoolExecutorを使うとスレッド数を制御・プールできて使い回せます。スレッドが終了したら、未来のオブジェクト(future)から結果を取り出せます。えっ、PythonはGILがあるから本当に重い処理はコアを生かしきれないって?わがままだな。そんなにCPUを発熱させたければ、ProcessPoolExecuterです。
import threading
import os
import concurrent.futures
import time

def executer_func():
    ident = threading.currentThread().ident
    print("start")
    for i in range(4):
        print("waiting " + str(i))
        print("current thread: " + str(ident))
        time.sleep(0)
    print("done")
    return os.getpid()


with concurrent.futures.ProcessPoolExecutor(max_workers=2) as executer:
    l = [executer.submit(executer_func) for i in range(4)]
    for future in l:
        print("=== result: " + str(future.result()))
ほら、これでスレッドじゃなくプロセスとして実行されます。CPUをこき使ってください。
でもなー、まあ、待たなくてもいいので、実行した結果がだけをもうちょっと処理したいんだけど・・・、って誰かが文句をたれています。Javaだと・・・、ってすぐにJavaを引き合いに出す人がいます。大丈夫です。タスクが終わったらコールバックを呼ぶことができます。Javaだと何かとオブジェクトを作ってめんどいですが、Pythonはそんなことは在りません。
import threading
import concurrent.futures
import time

def executer_func():
    ident = threading.currentThread().ident
    print("start")
    for i in range(4):
        print("waiting " + str(i))
        print("current thread: " + str(ident))
        time.sleep(0)
    print("done")
    return ident

def done_callback(future):
    print("=== result: " + str(future.result()))

with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executer:
    for i in range(4):
        future = executer.submit(executer_func)
        future.add_done_callback(done_callback)

futureにadd_done_callbackで処理が終わったときに実行する処理を指定できます。
まあ、大体分かったけど、発行したタスクが全部がちゃんと終わってから何かをしたいって?じゃあ、waitすればいいじゃん。と言うことで、

import threading
import concurrent.futures
import time

def executer_func():
    ident = threading.currentThread().ident
    print("start")
    for i in range(4):
        print("waiting " + str(i))
        print("current thread: " + str(ident))
        time.sleep(0)
    print("done")
    return ident


with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executer:
    l = [executer.submit(executer_func) for i in range(4)]
    results = concurrent.futures.wait(l)
    for result in results.done:
        print("=== result: " + str(result.result()))
concurrent.futures.waitですべてが終わるのを待ってくれます。その後、処理が終わったものを取り出して(result.done)、結果を処理するよろし。

executerのmapについても書こうかと思ったのですが、pythonの組み込み関数のmapと大体同じで面白くないのでやめました。
終わったモノから順番になるべく速く処理するときはconcurrent.futures.as_completedで取り出せます。

と言うことで、concurrentでした。本音を言えば、ループをみてJITがスレッドにできるところは勝手にスレッドにしてくれて、何もしていないのにある日突然、アプリケーションが高速化してくれるのが理想です。インテルのスレッディングビルディングブロックみたいに・・・。まあ、そこまで行かなくてもヒント(アノテーションとか)を書いておけばJITが解釈しやすくなるとかでも・・・。

次はaodag先生です。
でわでわ

2011年12月8日

Python Advent Calendar


Ariel Advent Calendarが始まって、順番が回ってきたら何を書こう?と戦々恐々としている毎日です。そんなことをよそ目に、@t2y がランチの時に英語で(僕の心象風景も含む)、

@t2y 「Hey, Ohtani-san. Please write something for Python Advent Calendar, or You'll be banished from "Asagumi".」

と脅してきます。僕が

@liris 「Oh, no! I haven't used Python 3 for a long time. I don't have antyhing to write.」

って言っても、聞き入れてもらえません。

@t2y 「This is a good opportunity to learn Python 3. You're over as a programmer if you stop studying. Huh?」

と薄ら笑いを浮かべています。 @t2y は朝組初代組長です。組長には逆らえません。渋々、参加することにしました。本当に触るのは久しぶりで、Python3のインストールから始まります。ざっと、モジュールのインデックスとか、新機能の説明とかを眺めて(眺めただけなのでかなり見落としています)、javaのconcurrentパッケージをぱくったと名高いpythonのconcurrentパッケージについて何か書くでしょう。

で、僕はいつ書くんだ?一通りサンプルコードも書いたので、後はエントリを書くだけです。

でわでわ

 

====

追記:一緒にいた@sasagon の証言によるとbanishじゃなくpunishと聞き間違えてないですか?と。まあ、どっちにしても怖いです。






2011年12月6日

Webページからファイルをデスクトップにドラッグアウトする

Gmailは、ChromeやFirefoxだと添付ファイルをデスクトップにドラッグアンドドロップで保存できます。IE? 何それ? おいしいの? なので、IEのことはよく知りません。IE8だと動いてくれませんでした。(Firefoxもウソだ。やっぱり動かなかった。)このページにその方法が書かれています。Drag and Drop APIっていうのを使うらしいです。とりあえず、サンプルコード。

<html>
  <body>
    <a href="some.png"
       draggable="true"
       ondragstart="event.dataTransfer.setData('DownloadURL',
        'image/png:some.png:http://localhost:8080/some.png');">
      file link
    </a>
  </body>
</html>

これだけです。リンクをドラッグアンドドロップえきるようにして、ondragstartイベントでdataTransferにsetDataするだけです。セットするのはmime typeとファイル名、ファイルへのリンクです。mime-typeはapplication/octet-streamでも大丈夫です。ファイルへのリンクは相対パスではダメで、絶対パスで書かないと行けないのがめんどいです。でも、これだけでデスクトップへのドラッグアンドドロップでの保存ができるので、簡単です。
でも、僕はドラッグアンドドロップではほとんど保存しないですが…

でわでわ

Ariel Advent Calendar

早いもので今年ももう12月です。12月と言えば、冬休み! ではなく、クリスマスです。クリスマスはみなさん、どのように過ごすのでしょうか?有り余る時間があるので、技術者ならハッキングして過ごすでしょjk、って誰かが言っていました。残念ながら僕は結婚しているので、そんなことはしません。

クリスマスを迎えるに当たり、はてなさんがAdvent Calendarを始めました。えっ、先を越されました。アリエルも負けてはいられません。いや、先を越されたので、負けています。いや、まだ、敗北を宣言するのは早いです。gihyoさんがAdvent Calendarをまとめたページを見てください。 会社の人が行う部門でHatenaさんより上です。ABC順だとか負け惜しみは言わせません。会社の名前を決めるとき、アルファベットでもあいうえおでも上位にくるようにわざわざ決めたのです。すべてはこの時のためです。

それでも、まだ、文句を言うんですか?Hatenaさんのページの画像とアリエルのページの画像を見比べてください。アリエルのCTOの許可も取らず、CTOをネタに遊んでいます。部下が上司をこけにするのはアリエルの文化です。アリエルでは会長ですらネタにされます。怖い会社です。

まあ、そんな感じで楽しんでください。

ちなみに、このエントリはAriel Advent Calendarとは全く関係のないエントリです。

でわでわ