わんくま横浜勉強会に参加したら発表してきた話.

わんくま同盟

昨日行われたわんくま横浜, nyaocat さんが発表するとのことでふらっと参加するかーと思ったら, 当日 nyaocat さんが風邪で病欠になっており, たまたま居合わせた僕があおいさんに見つかってしまい代理発表させられるすることになりました.

別に何の準備もしていなかったんですが, office にオートコレクトされてコンパイルエラーになるようなものだらけのスライドで20分発表した後, 闇鍋プログラミング勉強会のオープンステマをして, 最後に2月ごろにうちの院生の皆さん向けに作って公開していた Effective C++ になぞらえた C++11 時代のコーディングについて, あんどちんさんやえぴすてーめー先生などと議論形式というか, ツッコミ形式で話をして, なんとか発表時間50分を埋めましたとさ.

というか, よく考えたら Microsoft C++ MVP の居る前で「独自言語 VC++」とか最大級の dis をしたのはかなり勇気あったなと自分でも思います. だが悪いものに悪いというのはおかしくない!すみませんでした!*1

ちなみに当初発表予定だった Range と Iterator のスライドは僕は持っていないのでどうしようもないですが, 後半発表したスライドはあるので置いておきます.

あ, で途中突っ込みのあった strongly typed enum なんですが, enum -> interger へ変換するのは暗黙に変換可能ですが, integer -> enum は static_cast などをしてユーザの責任で enum の数値のどれかになっている必要があります. static_cast で integer -> enum の変換を行ったときの挙動は C++03 の enum でも同じ.

追記)enum class から integer へ変換するときも暗黙で変換できないっぽいです. ただ明示的に integer に変換できるのでより厳格になったと考えられます.

enum class Color {
  Red, Green, Blue
};

Color c0 = Color::Red;
Color c1 = static_cast<Color>(0);

assert(c0 == c1);

なんでこれ書いたんだろうと思ったら, 当時僕が enum 地獄に陥っていてアホみたいに長いプレフィックスが付いた enum を書き続けており, strongly typed enum 使えたらなあああが具現化してこうなっていたらしいです.

後, 型が指定できるようになったのが嬉しい. 発表中もありましたが OpenGL とか「色の値はこの型でビット並びはこうね」みたいなのが決まっているとき, 型が指定できるのは非常に使いやすいと思います.

後は仮想デストラクタの話, 仮想デストラクタは基本的に継承を考えているのであれば使わなければ死ぬわけですが, 継承を考えないときはパフォーマンス上の問題とか, 勝手に継承されて死ぬとかがあるので, 書いて欲しくない. 話にもありましたけど, 当時は仮想デストラクタは全部書けというのと, 可能ならば書かない, という本両方が存在していたようで, 理由がちゃんと書いてなかったりして暗黒時代っぽい感じらしいですね.

話を続けると, 継承を考える前に合成, コンポジションでなんとかする方法を先に考えるべきで, どうしようもなくなったときに継承を考えるのが良いと思います. なんだかんだで継承しなくて済むパターンの方が多いと僕は思いますので.

他にも色々言いたいことありましたが, 突然参加して発表して済みませんでした. 楽しかったです. ありがとうございました.

追記) 他の発表について

忙しすぎて忘れてた...

fadis_ さんの発表はプログラムに LLVM リンクして C++ の eval 作った的な話だったと記憶しているのですが, LLVM の内部の関数がメモリに展開するだけで, バイナリとしてファイルに一回保存しておきたいよね的な話がありましたね. それ Boost.Interprocess の Memory Mapped Files と Managed Memory Mapped Files を使えば, 後者でクラスオブジェクトを直接生成できる(Managed の方で用意されるアロケータが使えればいけたはず)気がするので, ファイル保存はできるが, 後はアドレッシング辺りが問題ですね. Interprocess には offset_ptr というメモリアドレスを相対的に表現できるような仕組みもあるので, がんばればいける?

えぴすてーめー先生*2 の発表は, 僕が Visual C++ を dis りすぎて恐ろしい反撃を食らったような感じがします. すみませんでした. というか TR2 既に実装されているところが出ていたということは知らなかった... イテレータのペアを取りたい時にどれを使えば良いのか, cbegin, cend の登場でさらにあれになってきた感じがします. C++11 は初心者に優しくなれたんだろうか... C++11 の話だけができればそうであるような気がしますね. C++11 の解説書籍もまだ全然ですし, Effective C++11 でないかなあ.

*1:助かった...

*2:変換できない...

CUDA の CRS spmv についてのメモ

Efficient Sparse Matrix-Vector Multiplication on CUDA | NVIDIA
の論文の、CRS spmv vector のメモ。

CRS spmv の場合、1行に複数のスレッドが計算したほうが効率がよい。
しかしある行で各スレッドが計算した結果を全て足し算 (parallel reduction) をする必要がある。

普通だったら、複数スレッドの reduction なので、スレッド間の同期が必要なのだが、上記の論文では half warp 単位でスレッドが動作するから、warp のスレッド数までだったら暗黙の同期が入るので明示的に同期を取る必要がない、という話。*1

なので、上の論文に記載されているカーネルコードのようにスレッド間の同期を明示的に書いてなくても問題ない。

蛇足というか思っていること

上のカーネルコード、グローバルのスレッド ID を計算して、そこから lane と row を計算しているんだけど、これってそれぞれ threadIdx.x , blockIdx.x でいいような気がするんだが... 何かあるんだろうか。

*1:warp を超えると複数の warp 間のデータを足し算するので明示的に同期が必要になってくる

第2回闇鍋プログラミング勉強会のお知らせ

ようやく会場とか日時とか決まりました。

第2回 闇鍋プログラミング勉強会 : ATND

日時:9/15(土)
会場:IIJ 東京本社 大会議室1(神保町)

希望調査時からご登録いただいた方には ATND にメッセージをお送りしました。

発表者がいないので誰か発表しましょう!
ちなみにプログラミング関連だったら何発表しても問題ないので、Twitter かメールでご相談ください!

一応 e-mail : krustf.cpp.ugmail.com

追記

ちなみに100人入る会議室なので60人ぐらいいないとガラガラで寂しいですよ!

gettimeofday よりも clock_gettime よりも boost.chrono.Clock

実行時間を図るとき、posix 系列なら gettimeofday で実行時間を測っていた。だいたいこんな感じ。

#include <cstdio>
#include <sys/time.h>
 
double second()
{
  struct timeval t;
  gettimeofday(&t, NULL);
  return t.tv_sec + t.tv_usec * 1e-6;
}
 
int main(int argc, char** argv)
{
  const double start = second();
 
  /* do something */
 
  const double stop = second();
  std::printf("generate time %f[sec]\n", stop - start);
}

最近知ったが、gettimeofday は deprecated らしい*1。clock_gettime を使うことが推奨されている。

Man page of CLOCK_GETRES

double second_high_resolution()
{
  timespec ts;
  clock_gettime(CLOCK_REALTIME, &ts);
  return ts.tv_sec + ts.tv_nsec * 1e-9;
}

gcc の場合 librt が必要なので -lrt フラグをつける。

一方 C++er は (std|boost) chrono を使った。

User's Guide - 1.50.0

#include <boost/chrono/chrono.hpp>

int main(int argc, chat** argv)
{
  using namespace boost::chrono;

  auto start = high_resolution_clock::now();

  /* do something */

  auto stop  = high_resolution_clock::now();

  // now 関数の返り値同士を引き算すると duration という型が返る
  // duration<double> にすることで秒単位の時間を得られる
  duration<double> sec = stop - start;
  std::printf("generate time %f[sec]\n", sec.count());
}

上の boost.chrono のドキュメントにある timer example そのまま。

std の実装は調べていないが、boost の実装を見た限り clock_gettime を使って Clock の now 関数を実装している。

high_resolution_clock は system_clock か steady_clock のどちらかで、steady_clock のほうが正確な時間を得られるようだ。


結論:boost.chrono で時間計測をする

*1:http://linuxjm.sourceforge.jp/html/LDP_man-pages/man2/gettimeofday.2.html

Boost.勉強会 #10 に参加しました

Boost.勉強会 #10 東京 - boostjp

もう二日経ったけど書く。

色々あったけど、最後に書くとして、各発表の感想。

Boost ライブラリ一周の旅 1.45.0 〜 1.50.0

C++Now! 2012 参加レポート

local function については、「あれ、auto でラムダ式を束縛すれば良いのでは?」と思ったのですが、それに加えて C++03 でも使えるように、ということなんですかね。

C++Now! の方は、結構楽しそうで結構行ってみたい。来年だったら4年生で研究室にこもるだけだと思われるので、お金を貯めて行ければ良いなと思っています。

そのためにも英語を精進します...

Sexyhook3 の改良点

実装に手を加えずに、侵入的に動きを書き換えるというのは、内部のテストをうまーく忍ばせたりとかできて大変嬉しい。

前にクラスのテストはそのクラス自身の公開メンバとして埋め込んでおけば、クラス自身の使い方も分かって一石二鳥では?とかもありましたね、そういえば。

C++でエレガントな並列計算

ここらで発表順変更。

「そもそもどこがエレガント?」
数値計算の速度比較なら fortran も要るのでは?」

とか色々言われていましたが、fortran は忘れてください(切実)。

あと、数値計算屋って for 文手書きが普通なの?とかもありましたが、他の方法でカウンタの値を取れれば文句ないです。

僕の場合、後は OpenMP で parallel for を使うのが多いので、割と手書きすることが多いです。

まあなんかこんな感じで count_for 関数テンプレートとか作れば良いのでは、とか思ったりするんですけどね。(適当に書いたので動くかは知らない)

template<class Counter, class Func>
void count_for(Counter begin, Counter end, Func f) {
#ifdef _OPENMP
#pragma omp parallel for
#endif
  for(Counter i = begin; begin != end; ++i) { f(i); }
}

万能数値計算型 URR

32bit でも現在の int をしのぐ膨大な桁を扱える。

ただ、その特性上 +1 〜 -1 の範囲外になると値のぶれが激しいとかなんとか。

特殊数 (NaN とか INF)を表現しないらしいので、一部の人にとっては非常に便利らしい。

C++ Transactional Memory言語拡張の紹介

Relaxed Transaction はキャンセル不可らしいのだが、使いどころが怪しい。

並列化したときに複数の状態を書き換える、書き換えようとしてエラーが生じたので巻き戻す、みたいな操作は欲しいことが多すぎるので、できれば欲しいな、と。

家に帰るまでが遠足です

タイトルは良いとして、Boost.Build の話。

「コンパイルして実行する」ところまでが C++ であって、「プリプロセス完了時には全てが終わっている」とか「コンパイルしたら全てが終わっている」とかは特殊な訓練を受けているのでまねしないでくださいね、という話。

まじめに書くと、bjam は feature とか、依存関係の伝搬とかでコンパイルも実行もしやすい環境が提供されているので、みんな積極的に使うと幸せになれます、という話。

デバッグビルドしたときとリリースビルドしたときで挙動が変わって実行時エラーが発生するとか結構あり得る話だと思うので、両方のバージョンを一緒にビルドしてテストできるのは良いなあ、と思います。

ディスカッション

僕がテーブルマスターをしたテーブルは最初ひどかったです。

色々与太話をしていたら、誰かが Concept ! と叫んで、妹!と叫んだら妹 Concept を作っていました。

僕の考えた最狂の妹 Concept

  1. いつも寄り添う
  2. 結婚しない
  3. 年を取らない
  4. トイレに行かない
  5. お風呂に一緒に入る
  6. 一緒のベッドで寝る

3番と4番を見て明らかに人間でない、という話をしていたら、誰が妹 Concept は人間 Concept を満たしていると言った?という話だったので、妹 Concept は人外にも適用可能です。

後、「妹がトイレに行かないとトイレで鉢合わせしてきゃーイベントができないじゃないか」と(たしか)あおいたんが「その発想はなかった」と全員が思った物言いをしてきたので、トイレ able な妹と non トイレ able な妹を定義することで解決しました。

後は割とまじめ、シャッフル後では、割と僕がうちの大学を dis ったりとか、Effective C++ は今買って読むのは微妙だとか、テンプレートで継承を無くせるとか、そもそも継承より包含を考えるべきとかって話をしてました。

最後のシャッフルでは、まさかのくらいおらいと先生が光臨なされましたが、終止 Concept の話で終わりました。ゆるい Concept 的な話は実は標準化委員会でも話があったらしく、考えていたら時間がなくなったので C++11 ではなくなったという流れだったとか。

懇親会と2次会

懇親会では、でちまるさんとくらいおさんが関西ネタで盛り上がっていた記憶しかないです。そして周りの他のテーブルが振り向く。

後、アキラさんから言われてしまいましたが、僕は一応某 A 社で働いてますよ?

この界隈の某社の社員&アルバイトも多すぎますが、某社への見学者も多すぎるぐらい居るような気がしました。

2次会は僕がなぜか行ってしまったのはカラオケでしたが、カラオケを歌えるほどの喉は既になく、謎の文書を読んでました。すみません英語だったので半分ぐらいしか理解できてないです。

歌おうとしたら、直前でタイムオーバーでした...

終わり

とりあえず、わんくま横浜行きたいので9月1日に闇鍋はしないことにしました。