2012年1月28日土曜日

どんどんと生産が海外に流れていくが…

もの作りの生産における人件費の占める割合って、いったい、いかほどのものなんだろうか?ソフトウェアのように、ほとんどが人件費のものならば、人件費が安いところで開発しようというのは、頷ける。酔っ払ってて、いまいち記憶が曖昧だが正月に自動車メーカーにいる友人と話てて、車のような大きいものでは、部品代と比較して人件費の割合なんて存外たいした事ないんじゃない?って聞いたような聞かないような・・・。  G+で知った「togetterにまとめきれなかった、グローバリゼーションの本質」にもあるように、世界の大衆車の販売を目指すのならば、やっぱり標準化してコストダウンしていかないと、お話にならないですよね?何が言いたいかというと、生産拠点を移しただけで勝てるとでも思ってるのかね?という事なんです。みんな、薄々そう感じながらも、コストダウン命で海外に生産拠点を移転ってやってるけど、本当に本質はそこですか?と、書いてみたかった。  競争するならスーパーカブのような車を作って、急須のようにデザイン性の高い民具レベルまで落とし込んだら、ロングセラーで商売してデザイン普遍で徹底的にコストを抑えるとか、逆に、もの凄いコンセプトカーを作って、ニッチな市場で高額販売するとか?  いや、どんどん生産拠点が海外に行ってる上に、NECが1万人削減とか、寂しい話が多いなーという訳で、書いてみました。

2012年1月24日火曜日

GeomagneticField に関する疑問

android のセンサーはカオスで、加速度系の方向が機種によって違うとか、いろいろ聞きます。 山をやる人には馴染みの磁北線ですが、国土地理院のページに詳しく書かれています。正確には測量によって算出されるもので、API に落としこむ Google は凄いなと思います。現在は時計回りを正とした場合、日本では反時計回り方向に磁北線があり、西偏X度というような表現をします。日本でも過去には東偏だった事があるようです。 さて、手持ちの機種 IS03, Regza AT3S0, Lenovo Ideapad K1 で検証したところ、方位は時計回りを正として表現されています。従って西偏として考えれば、北海道では9度ちょいなので時計回りを正とすれば、Android SDK の GeomagneticField.getIncrenation() で取得できるべき値は負であるべき気がしますが正。逆に GeomagneticField.getDeclination() で取得できる値は正であるべき気がするのですが負。API で取得できる値は正負が逆のような気がしてならない・・・。  もちろん、センサーで取得できる方位も時計回りが正なので、真北の補正は、
  magneticAngle - declination  // 間違い
  magneticAngle + inclination  // 間違い
だと思うのですが、ググッて見つかるのは magneticField + declination というものばかり・・・俺、間違ってるのかな・・・自信なくなってきた・・・。  ちなみに、SensorManager.remapCoordinateSystem から SensorManager.getOrientation の API を使って取得できる方位は単位がラジアンで、GeomagneticField.getDeclination で取得できる偏角は単位が度なので、注意が必要です。
2012/01/25 追記:  どうも、小学校からやり直しですな…。センサが方位0度を示している時、真北の値はX度な訳です。写像にすると、X度を0度にが補正写像な訳ですから、-X度を足し算すれば良い事になります。 従って、
  magneticAngle + declination  // 正解
  magneticAngle - inclination  // 正解
で良い事になります。あー、すっきりした。

2012年1月7日土曜日

あけおめー

皆さん、新年あけましておめでとうございます。
今年は嫁さんの実家に行って、その後、五色温泉~グスベリと、まわりました。

  お約束の五色温泉は、こんな感じです。










そして、坊ちゃんと、旧友の家族とで初滑りしたのですが、風が凄くて一本で敗退・・・。ほら、冬山に登ると空気が変わって、もの凄い厳しい風雪に見舞われる事があるじゃないですか?スキー場がそんな感じでした。旧友の坊ちゃん、うちの坊ちゃんより一歳年下なんですが、ちょっとだけ可哀想な感じでした…。

次はグスベリさんのところへ




ロケーションは、バッチシです。夜には、雪で寝かせた真狩村名産の百合根のグラタンが美味かった。







と、こんな感じの正月でした。

android 2重起動の禁止

いやー、android 開発、難しいですね~。こんな事は、もう語り尽くされているだろうと思ったかもしれませんが、もうちょい突っ込んだ内容になります。 android 関連の情報では、圧倒的にお世話になっている yanzm さんのところに Android launchMode の違いと、あるんで、基本は、これでオッケーなんです。  ところが、アプリケーションを終了して、直後に、アプリケーションを起動すると、一時的にアプリケーションというか、Activity が2重起動している状態になります。この時に初期化処理と終了処理が前後してしまう事があるんですわ。いやいや、ちゃんと行儀よくActivityを書いていれば、何の問題もないんです。どういう事をやっているかというと、
  
  ...
  class FooActivity extends Activity {
    public static Hoge hoge_ = null;
  ...
    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      hoge_ = new Hoge();
    }
    @Override
    protected void onDestroy() {
      hoge_.close();
      super.onDestroy();
    }
  ...
  }
みたいな事をやってるんです。フッ、static な global 変数ですか?って笑われるかもしれませんが、正直、あちこちの Activity が関連を持って利用しなければならないとなると、こうするより他無いんです。こんなんで共有できてしまうのは、将来的に地雷を踏む可能性もあります。だって、アプリケーション全体でデータを共有するためには、どうしたらいいですか?に対する回答は、「ApplicationBean を使いましょう」だからです。データは、Parcelable で受け渡しすべきです。さて、この android.app.Application ですが、onDestroy に相当するメソッドがありません。正直言って使えません。また、画面の回転でレイアウトが変わる度に onDestroy と onCreate が呼ばれるので、うざくてしょうがありません。だから、私はダミーの BaseActivity を作成して、そこで共通リソースの初期化と破棄を行なってます。そうすれば、MainActivity の onDestroy と onCreate が何回呼ばれようが気にしなくて済みます。  話を巻き戻して、SingleTask なのに一時的に2重起動してもプロセスが別なら問題ないんじゃないですか?と思うやないですか?ところが、違うんです。この2つのアプリケーションから hoge_ が共有できてしまっており、先に終了したアプリの onDestroy よりも先に、後から起動したアプリの onCreate がコールされる状況があるんです。いや、もうビックリですね?しょうがないので、
  ...
  class FooActivity extends Activity {
    public static Hoge hoge_ = null;
    private static int process_count_ = 0;
    ...
    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      if( 0 == process_count_ ) {
        ++process_count_;
        hoge_ = new Hoge();
      } else {
        ++process_count_;
      }
    }
    @Override
    protected void onDestroy() {
      --process_count_;
      if( 0 == process_count_ ) {
        hoge_.close();
      }
      super.onDestroy();
    }
  ...
  }
という感じで、プロセス?カウントをとって、対処してます。ちなみにタイミングがシビアじゃ無いので、カウントの保護は一切行なっていません。 追記:static 変数の記述場所を間違えてたので修正しました。やっぱりカウンタは同期保護した方が良いかもしれません。synchronized(this)ではダメっぽい気がしますが、突っ込んでません。やるとすれば private static Object sync_ = new Object(); しておいて、synchronized(sync_) でしょうか?
訂正: final 修飾子が余計だったのを取った。
2012/01/15 追記: どうも、Activity 再開時の挙動など、singleTask 等で細かく異なるようである。参考になるサイトを見つけた。こちらも目を通した方が良いです。一旦 HOME ボタンを押した後に再開すると、singleTask では BaseActivity の onDestroy がコールされるので思わしくない。そこで、このような事をやる場合は、singleInstance を選択する事にしました。 singleInstance は、Activity のフォーカスが外れる時点で、onDestroy がコールされ破棄されるので、使えない。別に single である必要は無い気がしてきた…。もう少し突っ込んで、整理した後に書く予定。追試する度に、挙動が違って困る…。
 2012/01/17 追記: BaseActivity に Manifest で android:screenOrientation="landscape" と指定するようにした。 BaseActivity -> MainActivity と表示している時にレイアウトの縦横が変更された時、MainActivity だけが変更の影響を受けるわけではなく、BaseActivity にまで変更の影響を受けている事がわかった。そのせいで、BaseActivity の onDestroy と onCreate がコールされる事になる。この辺の挙動は、かなりトリッキーだ。BaseActivity の onCreate 時に MainActivity を起動しているのだが、MainActivity が縦横変更時にどんどん増殖するという恐ろしい事態を引き起こしていた。現在は、singleInstance で実装している。
2012/08/29 追記:Android SDK における sqlite3 のコードが、データベースを開いたプロセスと閉じたプロセスが同一でないと、エラーで動作しないようなチェックが入っております。なので、最終的には、2重起動を自前で禁止するために、process_count_ >= 2 ならば、アプリケーションを終了するようにしました。  一方のプロセスがデータベースを閉じるまで待ってからオープンしようと synchronized メソッドでカウントを検知したら、そこから抜けてThread.sleep(200); とか入れてみたんですが、プロセス|スレッドのコンテキストが全く切り替わりません。このため、2重起動を自前で防ぐコードを選択せざるを得ませんでした。こういうのは、singleInstance を指定しているんだから、アプリがやる仕事じゃ無いと思います。

2011年12月8日木曜日

アイデアを形にする(「アイデアの99%」を読んで)

アイデアの99%」を読むまで、自分のタイプを自覚できていなかった。厳密には、自覚はあっても、どうすべきかまでは思いが至らなかった。自分のタイプは、興味があちこちに移り、ひとつの事に集中できないと思えば、他の事が頭に入らないほど考え込んでしまったりで、夢追い人。片づけ魔では無い。
くどくて退屈な本「イノベーションの神話」には、死蔵していったアイデアの話が載っており、何か特別なアイデアが適切なタイミングで実現されなければいけないような事が書かれていたから、思い違いをしていたのだ。
アイデアを実現する=ビジネスで成功する=スタートアップで成功する=政策を実現する=日本を変える=...とにかく何でも良い。そのためには、適切なアクションを起こすための仕組みを作る事だったのだ。アクション・メソッドに落とすとは、プロジェクト管理をキッチリと行う事に他ならない。アクション・メソッドとは、アイデアを実現するために、誰か(協力者・社員・パートナー・下請けなど)にわかる形(作業指示書)へ分解して推し進める単位である。
日本にはビジョナーがいないのではなく、プロジェクトを組んで仕事をするノウハウが足りないだけなのではと思う。

 自分の視点が変わったせいか、ひとつの事に取り組む姿勢を指摘した書き物が目につくようになった。しかも、ここ最近、よく目にする。一種のシンクロニシティを感じているところなのだ。これは決して偶然なのではなく、社会的な要請が、そこにあるからだと思う。(つい最近、目にしたものでは、瀬戸内寂聴先生の本で、政治家が「あれもやりたい、これもやりたい」と八方美人的に語っているのを叱責するもの。Software Design の震災でうまくいっているプロジェクトの特徴を述べたもの。など)

 日本の文化として、17条憲法にあるように「和を以て貴しと為す」が根底にあるのかどうかしらないが、和を歪曲しているからなのかもしれない。あれも良いよね?うんうん、でも、これも良いよね?うんうん。でも、あれをこうしたら良いんじゃない?うんうん。良いよね談義で終わってしまっているのではないか?思い返せば、学校教育からしてひどかった。「何々についてどう思いますか?」「何々だと思います。」「何々してはいけないと思います。」「何々しないように気をつけましょう。」終止抽象的な話で終わって、これがアクション・メソッドにブレークダウンされるような事は無かった。アクション・メソッドは有っても、プロジェクトを組んで自分の頭で考える訓練なぞ皆無ではなかったろうか?お上ならぬ大人の考えたプログラムを実行する訓練ばかりでは無かったか?

 何事かを成すためには、一見、たいした事がないように思える事でも、多大なリソースが必要なのだ。特にグローバル競争で、中途半端なものは生き残れない。だから余計に最後までやり抜く覚悟が必要なのだ。やり抜くためには、実現するための具体的なアクション・ステップ(プロセス)に落とし込み、プロジェクト管理を行って、一歩一歩前進しなければならない。

 ソフトウェア業界に目を移せば、TPPで仕事がグローバルになっていけば、アイデアを形にするためのプロジェクト管理という手法は必須であり、避けて通れない問題になっていくでしょう。海外では、ファンクション・ポイント法により見積もりを作成し、予算と期間を決めて契約を行う時には、インセンティブ契約というのを結ぶ事もあるそうです。このインセンティブ契約とは、定数人員で期間が短工期に仕上がった場合、受注金額の残工期分を、発注側と受注側で折半するというもの。これでは、プロジェクト管理をしっかりとハンドリングし、本当に実績を上げているグローバルな会社と競争した時に勝てるはずもない。これは何もソフトウェアだけに限った話ではなく、官僚丸投げの政治家にも言える事であります。マネジメントされていないプロジェクトの行き着く先は、不幸そのものです。

 逆算で考えて行くと、アイデアを形にするためには、プロジェクト管理が必須であり、プロジェクト管理をするためには、何をゴールとするか明確なビジョンに落とし込む作業が必要なわけです。そのためにはマネジメントが必要で、ビジョンを伝え共有し、共有されたビジョンが何らかの形でプロジェクトの血となり肉となる必要があります。アイデアを形にするために足りないリソースがあれば、外部から持ってくる(調達)。これが、プロジェクト・チームとなるわけです。アライアンスの時代と言われていますが、1+1=3なのではなく、"H" + "e" + "l" + "l" + "o" = "Hello" な時代というのが本質では無いかと思います。

 それでは、どんなアイデアを形にすべきか?闇雲にアイデアを形にしていったとしても、事業として成り立たない可能性だってあります。俗に言う「スタートアップは、どんな問題を解決するのか?が明確でなければならない」とは、世の人々のために役立ち支持され、事業として成立するようなアイデアですか?を端的に問うたものです。ITにより様々なルールが変更され、従来のビジネスモデルが成立しない中、何を選択し、何に集中していくのか?マネジメントに携わる人は、本当に厳しい課題を突きつけられていると思います。

 尚、多数の本に登場するイノベーションを生み出す企業というのは、レベルが高すぎて一般企業の参考にはなりません。そういう意味では、ここで述べた論は、最低限の一歩を踏み出すためのものです。

追伸:技術者としての生き方についての考えは、後日、改めてエントリーにするかもしれません。

2011年12月3日土曜日

ブログの役割(時代は、やっぱりソーシャルなのかもしれない…)

Bloggerのレイアウトを元に戻した。動的ビューは、全体を見渡すには良いのだが、コード等が読みにくい。で、統計を見てみたのだが、投稿の内容によって閲覧のバラつきが顕著である。自分のポストする内容も、ごった煮なので波長の合う投稿と合わない投稿の格差が激しいというのも考えられるのかも..
 ブログの時代は終わった…とする煽り記事を目にする事もあるが、ブログに求められる役割が変わりつつあるのではないか?という気がしている。
  • Twitter をやる人ならば、ちょっとした事は呟けば良い
  • 今日こんな事があったよ。それいいね!共感を得たければ Facebook にポストすれば良い
  • なんか知らんけど、ワーッと固まって騒ぎたければ Google+ にポストすれば良い
 Facebook というのは、連帯感を演出するには良いが、私には、ちょっと息が詰まる感じがして、そんなに楽しく無い。今はまだ、G+民というのは、どことなくギークっぽい人が多くて面白い。もしかしたら各サービスの役割が既に定着しているので、G+では、カテゴライズされたサークルを形成するというのが G+の役割なのかもしれない。嫁さんのブログの使い方だと、半分匿名のような緩い繋がりがあるようである。ただ、この繋がりは Twitter,Facebook,G+ 等に侵食されている気がしてならない。こうやって考えると、やっぱりソーシャルなのかな?と思う。ソーシャル、ソーシャルつうけど、元々、人間は社会的な生き物なので、その本質がデジタルになっただけなのだろう。

 では、ここでブログの役割について考えてみよう。
  • 独り言日記
  • ある分野に特化した情報
  • 密度の濃い情報
  • 距離を置いたマスメディア的な繋がり
と、こんなところに集約しつつあるでは?
相互的な繋がりが薄れている以上、トラックバックを削るという動きは、仕方が無いのか?
役割が絞られてきた以上、ページビューを稼ごうと思ったら、ブログに書くテーマは絞った方が良いだろう。逆に自分のスタイルを貫き通すのならば、ページビューに拘ってはいけない。

と、偉そうに分析してみたけど、どうブログを書こうと自由な事に変わりは無い。

2011年12月1日木曜日

インテル ソフトウェア カンファレンス 2011 札幌に参加してきた

札幌JRホテルで開催され、昼食付きで、「Cilkがやってきた」という本まで貰って、高速並列化の話まで聞けて凄いカンファレンスでした。なのに、席が空いている…。これはもったいないです。2012年も開催したいそうなので、札幌のC++の技術者は是非とも参加するようにしましょう。

 最初のセッションは、intel CPU Sandy Bridge の最適化について、SSEの流れを汲むベクトル・エクステンションのバス長が2倍の256に拡張されたAVXというものが登場とか、1次キャッシュ~3次キャッシュの構造やら、分岐予測の話やら、ロード+演算の組がμops になった話、最初からレジスタにZEROを割り当てるゼロ・イディオムの話、プリフェッチ・キューの話やら、深良い話が聞けた。ハイパースレッドでは、コアで、キャッシュを共有するよなんてのは知らなかったです。
 tipsぽい話では、Sandy Bridge では、ローテーションとシフトの速度が逆転してますよとか、16bit命令と32bit命令を混在させるとペナルティ食らいますよとか、ロードバンク衝突があるので先にロードを済ませましょうとか、将来的には、CPUによる乱数生成命令がサポートされますよとか、RSDTC の拡張命令として、コア番号と経過クロックの組を返す命令がサポートされますよとか…。こうやって振り返ってみると、結構ボリュームがあります。

 続いて、インテル Parallel Studio XE の使い方から、コンパイラ・オプションの話。これまた、ためになる内容が盛りだくさん。普通はインテルのコンパイラを使うだけで、何もしなくても 30%ぐらいは速くなるから、人を導入して速度アップをするぐらいならコンパイラ買った方がマシって事になるみたいです。デモの内容を見ても、実際速くなってました。C++のコードを使って、OpenMPやら、自動ベクトル化(SSE命令)をしてマルチスレッドによる高速化なり、ベクトル演算による高速化なりを実現。コンパイル・オプションで最適化のヒントなんてのもあって、/Qguide4 とかすると、コンパイラが、「ここのベクトル化に失敗したでー」「ここのループは、マルチスレッドで並列化した方がいいでー」とか、べらべら羅列してくれて、面白い。

 インテル Cilk Plus によるソリューションというセッションが、また面白かった。OpenMP を使って並列化させる事は、できるけども職人技が必要で、速度を上げる事は難しい。例えば、並列化するにあたって、ジョブの割り当てを工夫しないと1つのスレッドに負荷がかかって他のスレッドが遊んでしまうとか、メモリ・キャッシュを考慮して処理単位をメモリが集中している粒度に分けて並列化するとか、奥が深い。これらの問題をもっと簡単に書けるようにしましょうというのが、Cilkだ。
 ちなみに GCC の次期バージョンでは、Cilkが実装されると決定しているようなので、決してインテル独自の仕様に留めるつもりでは無いようです。Cilk の特徴は、大きく3つあるように思います。

 1つ目は、MapReduce のように、並列化をサポートするための仕組みをサポートする事。下のコードは、動作検証していないので、雰囲気だけ味わってください。
cilk::reducer_list_append<char> res;
  cilk_for(int i = 'A'; i < 'Z'; ++i ) {
    res.push_back( static_cast<char>(i) );
  }
 こうする事で並列化しながら順序を保って処理がされます。cilk::reducer_opadd<int> とかを宣言して、合計の計算を並列化してみたりできます。

 2つ目は、副作用の無いループ中の演算表現。関数型言語を勉強していると、ピンとくるかと思います。私は、こう解釈しましたが、本当は、コンパイラがSSEの命令を使って最適化しやすい表記を考えたら、こうなったって事なのかもしれません。これも動作検証は未です。
y[:] += a * x[:];
 配列に対して、レンジ演算が記述できます。

 3つ目は、自動負荷分散。処理の単位をCilkが自動で分割し、スレッドへの処理割り当てを自動化してくれます。

 特別講演は、ディジタル・ワークス株式会社さまのインテル・コンパイラー導入事例紹介。TBB の allocator とか、tbb::concurrent_hash_map,tbb::concurrent_queue とか、速くていいです!との事。

 最後にインテル・アーキテクチャにおける並列分散処理のための技術交流サイト IA Software User Society がオープンしたので、皆さん是非参加してくださいとの事でした。会員になると、特別な資料とかも用意されています。無料です。

 インテル・ジャパンの皆様、XLsoftの皆様、ディジタル・ワークスの皆様、ありがとうございました。楽しかったです。

追記:Cilk は強烈で、今後を占う上で重要な役割を担いそうな印象を持っているのだが、この書き込みは人気が無いようだ…。