2012年7月21日土曜日

IBM BlueGene/Qのセミナーを受けてきたよ


IBM東京本社で行われたBlueGene/Qのセミナーを受けてきました。ブロガー向けセミナーということで、IBMの顧客でもなんでもない私がセミナーを受けてきました。2時間超にわたるセミナーの全貌を紹介するわけにはいきませんので、いくつかポイントを記しておきたいと思います。

BlueGene/QはIBMが開発したスーパーコンピューター(HPC)です。

HPCは、通常のコンピュータでは行えないような大規模な科学計算を行うことを目的に作られたコンピュータです。流体力学など、複雑な非線形現象のシミュレーションに主に使われます。計算科学という、理論、実験に続く、第三の研究手法を実現しています。

BlueGene/Qを使ったSequoiaという米ローレンス・リバモア研究所のHPCが、日本の富士通による"京"から世界最高速の座を奪取したことで話題になりました。BlueGene/Qは、他にも多くの顧客に導入されており、HPCのTop20に数多く食い込んでいます。

BlueGene/Qの特徴は、低消費電力(他機種にくらべ、2倍を超える電力効率)、省スペース("京"にくらべ、1ラック当たりの性能が17倍)であることです。

なぜ低消費電力と省スペース性が重要になるかというと、現在のHPCは、とてつもなく巨大で電力をバカ食いするようになっており、それが性能を頭打ちにする限界になっているからです。

電力を食えば、熱を出すので、その熱をうまく排出しなければなりません。スペースを食えば、それだけ長い距離の配線をせねばならず、配線だけでも大変なことになります。

日本の"京"は、たしかに高性能なのですが、BlueGene/Qに比べると電力効率やスペース効率で劣るために、巨大な体育館のような専用の建物を必要としています。これでは、普通の研究所などに導入することができません。

"京"は、「2位じゃダメなんですか?」という言葉で有名になりましたが、世界最高速のHPCを作ること自体は、科学的、産業的にはあまり重要な意味の無いことです。HPCは科学に使われて初めて意味をなします。研究所などに導入しやすいBlueGene/Qのようなシステムを作って、多くの大学や研究所に導入して誰でも使えるようにすることこそ意味があることです。その点では、BlueGene/Qの導入実績を見れば大成功といえます。

IBMの説明によると、"京"も、電力効率で、他の通常のx86+GPUベースのHPCに比べると優れているということです。しかしBlueGene/Qの圧倒的な効率の前には、それもかすんでしまいます。

IBMはBlueGeneシリーズを10年以上前から研究しており、一貫して低消費電力にフォーカスしてHPCを開発してきたということです。組み込み用のPowerPCプロセッサを低電圧、低周波数で動かすことで、高いワット当たり性能を確保しています。

また組み込み用プロセッサをSoCとして、通信回路など全ての回路を一つのチップにまとめています。外部に必要なのはDRAMだけです。それと水冷機構を使うことで、驚くべき高密度実装を可能にしています。ラック当たり16,384コアという驚異の密度です。

そのため、計算機室にサーバラックを4つか5つならべれば、世界最高クラス(ペタフロップス級)のHPCが手に入るという寸法です。水冷なので、工事などはちと面倒かもしれませんが?

BlueGene/Qも、その他のHPCと同じようにLinux+MPIという並列プログラミング環境による標準的なコードを動かすことができるそうです。一つのプロセッサあたり16コアを含み、64スレッド並列で動かすことができます。各コアとメモリはクロスバーで接続されSMPとして動作します。(Intelがクロスバーを諦めてNUMAにしているのとは対称的ですね。なぜ設計思想が違うんだろう?)

IBMでは、BlueGene/Qの他にも、x86ベースのHPC、Power7ベースのHPCを販売しています。顧客によって、スレッド当たりの性能や、I/O性能などのニーズが異なるため、多様なラインアップとしているそうです。

今後しばらくハイエンドのHPCはBlueGene/Qの独壇場となるでしょう。100年以上前からコンピューティングの最先端に居続けるIBMという企業の実力は驚くべきですね。我々ウェブデベロッパには全くご縁が無い企業ではありますが・・・

IBMもPower 7を使った大型HPCプロジェクトのBlue Watersの開発に失敗し、プロジェクトから撤退していたりするので、もちろん彼らも万能というわけではありませんが。

"京"はそもそも完成した計算機の性能で一位を目指すのではなく、製品自体の効率や売上で一位を目指すべきでしたね。

参考記事:

2012年7月20日金曜日

A/BテストツールのOptimizelyを使ってみた


Optimizelyは、ウェブサイトのA/Bテストを行うための洗練されたソフトウェアです。

A/Bテストとは、ダイレクトマーケティングでは昔から使われてきた手法で、顧客に対して2種類のダイレクトメールなどを行って、反応が良いものを選び出す、実験の手法です。

これによって、マーケティングのような感覚的な分野においても、データをもとに改善を積み重ねる経営を行うことができるようになります。

最近では、ウェブサイトにおいても顧客にN通りのパターンを見せて、どれが購買に結びつくかなどのA/Bテストを行うことが増えてきました。

A/Bテストツールには色々なものがあり、Google Analyticsなど無料のものもあります。

その中で、Optimizelyは有料ですが、使いやすさに特化されており、話題を集めています。

Optimizelyを使ってA/Bテストを行う場合、HTMLエディタを使ってWYSIWYGで変更内容を編集する方法と、Javascriptを自力で書く方法があります。

静的コンテンツであれば、HTMLエディタで簡単に編集することができますので、プログラマ不要でA/Bテストを行うことができます。

動的コンテンツは、自力で変更案を適用するJavascriptを書かなければなりません。それでも結果測定、集計や統計検証などは自動で行ってくれ、美しいグラフも書いてくれるので、それなりに役に立ちます。

実際に弊社でもちょっとした文字の変更などを試してみたのですが、クリック率の0.7%改善という結果が得られました。しかし、もっと大幅な改善を期待する場合には、変更案を考えるのがなかなか大変だなー、と思いました。

円高の昨今ですから、月79ドルの利用料は高いものではありませんが、月間20,000ページビューを超えると1,000ページビューあたり7ドルという高額の追加料金を取られるので、それは結構問題です。

Google Analyticsなら無料で使えますから、そちらの機能で満足できる人は、あえてOptimizelyを使うまでもないでしょうね。でもたぶんGoogle Analyticsのウェブテスト機能では物足りないし、サポートも足りないので使い物にならないと思いますけど。

今の時代、A/Bテストを使ってウェブサイト反応率を改善していくのは常識になりつつあります。われわれウェブ業界人はA/Bテストツールの一つや二つは使えるようになっておく必要があるのではないでしょうか。

2012年7月12日木曜日

Amazon DynamoDBがウェブのインフラを塗り替える

Amazon Web Services (AWS)は、すごい勢いで機能を増やしており、いわゆるクラウド業界の中で圧倒的な存在感を示しています。AWS = クラウドと言っても過言では無いでしょう。

AWSは、他のレンタルサーバーやホスティングと比べたり、自社でデータセンターを借りるのに比べると、だいぶ割高な設定になっています。しかし、その機能は他のサービスを圧倒しています。

AWSがすごいのは、分散ストレージであるS3などの分散システムを管理不要で提供していることです。

分散システムには、耐障害性、性能(スケーラビリティ)などの点で大きなメリットがありますが、実際に分散システムを管理運用するのはとても面倒で煩雑な作業になります。弊社でも分散ストレージを自社開発運用していますが、かなりややこしく、可能な限りやりたくない作業です・・・

とくに分散システムのソフトウェア開発者と、分散システムの管理運用者が異なる場合には、ハードウェアとの相性や、ソフトウェアの細かい癖、ソフトウェアのバグなどを克服してうまく分散システムを運用するのは至難の業となります。

そのため、弊社では、わざわざ自前で分散ストレージのソフトウェアを自社開発しています。機能が少ない簡易的な自社製品の方が、機能が多くて挙動が完全に把握できない他人の作品よりもマシだからです。

その点で、自前でソフトウェアを開発し、サービスを自前で運用しているAmazon Web Servicesは、分散システムの理想型と言えます。これができる企業は、世界でも多くはないでしょう。

Amazonのさらなる強みは、Salesforceのようなエンタープライズ業界の企業と違って、ずっとセンスの良いAPIや使い勝手の良いUIや分かりやすいドキュメントを提供していることです。


さて、本題に移ります。

先日登場したAmazon DynamoDB (分散NoSQLデータベース)には私も強い興味を抱いており、このたびAmazonが開催したDynamoDBセミナーに参加してきました。そこから得たDynamoDBの情報と印象をお伝えしたいと思います。

私はMongoDBなどの既存のNoSQLには極めて懐疑的な見方をしていました。先述のように、分散システムを運用し、期待通りの性能を安定してたたき出すにはかなりの苦労が伴います。それを考えると、どうしても極めて高いスケーラビリティの必要なソーシャルゲーム業界など以外では有用性はないだろうと考えていました。

しかしDynamoDBは違います。テーブルを作成し、必要なスループット(毎秒の読み書き数)を設定するだけで、勝手に分散データベースを自動で作成・運用してくれます。スループットはリアルタイムに変化させることも可能です。これなら何の苦労もなく分散データベースを運用することができます。

DynamoDBの特徴は、極めて簡単な運用、驚愕のスケーラビリティ(高い書き込みスループット)、高可用性の3つです。スケーラビリティは驚くほどで、最高で、秒間200万リクエストの実績があるそうです。データは自動的にリージョン内の3つのデータセンターにレプリケーションされ、高い可用性を誇ります。

DynamoDBの弱点は、現時点では機能がめちゃくちゃ限られていることです。複雑なクエリはもちろんのこと、テーブルにプライマリキー以外のインデックスを貼ったり、バックアップを取ったりする機能すら標準では備わっていません。なんとデータ型も、整数と文字列とそれらの集合の4種類しかありません。

複雑なクエリを実行したり、バックアップを取ったりするためには、Elastic Map Reduce (Hadoop)を利用して、Hiveというクエリマネージャを使ってクエリを実行する必要があります。これははっきりいってややこしいです。

しかしワークショップに参加して、実際にコーディングをして使ってみて思ったのは、実際には意外と色んな用途に使いやすいかもしれないということです。

EC2から同リージョンのDynamoDBにアクセスする場合、レイテンシは極めて短く、データも高速に転送されます。そのため、誇張気味に言うと、ローカルにあるファイルのような感覚で扱うことができます。これなら、小規模システムの場合は、インデックスなど使わずとも、フルスキャンを多用しちゃってもいいのかな、と思いました。

かなり曲者で使いこなしが難しい印象のDynamoDBですが、既にかなり導入実績があり、どんどん売上が伸びているそうです。ソーシャルゲームなどの業界にとっては福音と言えるのでしょう。

将来的に、二次インデックスがサポートされ、データ型もいろいろと実装されてきて、複雑なクエリをうまく実行できるライブラリなどがでると、ソーシャルゲーム業界に限らず、一般のシステムも一部はこれで置き換えられていくのではないかなと思います。RDBMSの運用はいささか面倒ですからね。

EC2, S3, DynamoDB, Cloudfrontの登場によって、スケーラビリティや高可用性を実現するということはお金さえ払えば誰にでもできる仕事になってしまったな、という印象です。

弊社としても、今後はAWSの使いこなしに力を入れていこうと考える次第です。


ところで、Amazonワークショップ内で、2時間で「並列的にニコニコ動画のタグをクロールして集計するスクリプト」を書いたので、おまけとして以下に乗せておきます。DynamoDBの並列性を確保する機能であるConditional PutとAtomic Counterを活用することで、簡潔に並列集計を実現しています。

require 'uri'
require 'net/http'
require 'kconv'
require 'rexml/document'
require 'rubygems'
require 'aws-sdk'

AWS.config({
  :access_key_id => "",
  :secret_access_key => ""
})

dynamo_db = AWS::DynamoDB.new(:dynamo_db_endpoint => "dynamodb.ap-northeast-1.amazonaws.com")
videos = dynamo_db.tables["nicovideo_videos"]
videos.load_schema
tags = dynamo_db.tables["nicovideo_tags"]
tags.load_schema

# タグ収集、カウント

loop {
  vid = (rand * 17392999).to_i
  video_id = "sm#{vid}"

  puts video_id
  begin
    url = URI.parse("http://ext.nicovideo.jp/api/getthumbinfo/#{video_id}")
    http = Net::HTTP.new(url.host, url.port)
    result = http.get(url.path)

    xml = REXML::Document.new(result.body)

    next unless xml.elements['//title']

    title = xml.elements['//title'].text
    puts title
    videos.items.put({"video_id" => video_id, "title" => title},{:unless_exists => "video_id"})

    xml.elements.each('//tag') { |tag|
      tag_name = tag.text
      puts tag_name
      t = tags.items.put({"tag_name" => tag_name, "count" => 1}, {:unless_exists => "tag_name"}) rescue nil
      unless t
        t = tags.items.at(tag_name)
        t.attributes.add({"count" => 1})
      end
    }
    puts "\n\n"
  rescue Exception => e
    p e
  end
}

# 集計

rank = {}

tags.items.select { |tag|
  count = tag.attributes['count'].to_i
  tag_name = tag.attributes['tag_name']
#  puts "#{count}: #{tag_name}"
  rank[count] ||= []
  rank[count] << tag_name
}

rank.keys.sort[-10..-1].reverse.each_with_index { |count, i|
  puts "#{count}件: #{rank[count]}"
}