57
僕はどうして Boost.Proto ぺろぺろしようとしたのか。 Boost.勉強会 #4 2011/02/26 ふじた のりひさ/@fjnli id:fjnl 1

Boost.勉強会#4 Boost.Proto

  • Upload
    fjnl

  • View
    3.300

  • Download
    2

Embed Size (px)

DESCRIPTION

http://atnd.org/events/11551

Citation preview

Page 1: Boost.勉強会#4 Boost.Proto

僕はどうして Boost.Proto をぺろぺろしようとしたのか。

Boost.勉強会 #4 2011/02/26

ふじた のりひさ/@fjnli id:fjnl

1

Page 2: Boost.勉強会#4 Boost.Proto

2

とある Twitter の会話履歴 (ログ) ...

Page 3: Boost.勉強会#4 Boost.Proto

最初の発表だれがいいですかhttp://atnd.org/events/11551

3

Page 4: Boost.勉強会#4 Boost.Proto

最初の発表だれがいいですかhttp://atnd.org/events/11551

Protoのどんな所がききたいですか。

3

Page 5: Boost.勉強会#4 Boost.Proto

最初の発表だれがいいですかhttp://atnd.org/events/11551

Protoのどんな所がききたいですか。

Lambda, Spirit, uBLASがあるいま、Protoで 何を作るのか 。

3

Page 6: Boost.勉強会#4 Boost.Proto

僕はどうして Boost.Proto をぺろぺろしようとしたのか。

4

Page 7: Boost.勉強会#4 Boost.Proto

5

Boost.勉強会#4の発表に「なぜ僕はProtoをぺろぺろするのか(仮)」というタイトルがありますが、ぺろぺろする理由とか全く聞きたいと思わないので Protoのことについて話してください。

Page 8: Boost.勉強会#4 Boost.Proto

Agenda

•はじめに

• Boost.Proto のお話

•僕がぺろぺろした理由

•まとめ + 質疑応答

6

Page 9: Boost.勉強会#4 Boost.Proto

Agenda

•はじめに

• Boost.Proto のお話

•僕がぺろぺろした理由

•まとめ + 質疑応答

6

いまここ

Page 10: Boost.勉強会#4 Boost.Proto

Agenda

•はじめに

• Boost.Proto のお話

•僕がぺろぺろした理由

•まとめ + 質疑応答

前半15分ぐらい

後半5分ぐらい

6

いまここ

Page 11: Boost.勉強会#4 Boost.Proto

Agenda

• Boost.Proto のお話

• Boost.Proto は縁の下の力持ち

• Expression Template (ET) の型

• Boost.Proto の拡張方法

7

Page 12: Boost.勉強会#4 Boost.Proto

Agenda

•僕がぺろぺろした理由

•数値計算に Boost.Proto を使う

• Boost.uBLAS では満足できない理由

•General Purpose computing on GPU (GPGPU)について少し

• ET → 関数呼び出しの列への変換

8

Page 13: Boost.勉強会#4 Boost.Proto

自己紹介

•ふじた のりひさ (藤田 典久)

• @fjnli, id:fjnl•東京都の端の大学 → 山奥の大学院 (見込)

•Ariel Networks バイト

•研究テーマ: GPU を用いた数値計算

9

Page 14: Boost.勉強会#4 Boost.Proto

自己紹介

•ふじた のりひさ (藤田 典久)

• @fjnli, id:fjnl•東京都の端の大学 → 山奥の大学院 (見込)

•Ariel Networks バイト

•研究テーマ: GPU を用いた数値計算

9

Hatena IDに i はいりません

Page 15: Boost.勉強会#4 Boost.Proto

自己紹介

•ふじた のりひさ (藤田 典久)

• @fjnli, id:fjnl•東京都の端の大学 → 山奥の大学院 (見込)

•Ariel Networks バイト

•研究テーマ: GPU を用いた数値計算

9

Hatena IDに i はいりません※ 本人も間違えました

Page 16: Boost.勉強会#4 Boost.Proto

自己紹介

•ふじた のりひさ (藤田 典久)

• @fjnli, id:fjnl•東京都の端の大学 → 山奥の大学院 (見込)

•Ariel Networks バイト

•研究テーマ: GPU を用いた数値計算

10

Page 17: Boost.勉強会#4 Boost.Proto

前半.begin();

11

Page 18: Boost.勉強会#4 Boost.Proto

Proto 概要

• Expression Template (ET) の構築を補助するライブラリ

• a + b * c → plus<A, multiply<B, C>>

• Boost 1.37 で導入された

•Headers only

12

Page 19: Boost.勉強会#4 Boost.Proto

Proto は縁の下の力持ち

• Boost.Proto は単体で利用して嬉しいライブラリではない

• Boost 中の Boost.Proto ユーザ:

• Boost.Spirit (Qi, Karma, Lex)

• Boost.Phoenix v3 (in the future)

• Boost.MSM.eUML (experimental, 1.44)

• Boost.Xpressive

13

Page 20: Boost.勉強会#4 Boost.Proto

ETの型

•割と重要

•エラーメッセージで頻出

•一般的におそろしく長い (´・ω・`)

•Qi で Proto 関係の部分でエラーを出すと遭遇する

14

Page 21: Boost.勉強会#4 Boost.Proto

15

namespace proto = boost::proto;using namespace boost::proto;using boost::proto::argsns_::list2,using boost::proto::exprns_::expr;using boost::proto::exprns_::term;

紙面の都合で、以降、特に断りがない場合、以下に示す using 宣言を暗黙に行なっています。

Page 22: Boost.勉強会#4 Boost.Proto

a[b] + (c * d)

16

構文木 (Syntax Tree) で表すと:

Page 23: Boost.勉強会#4 Boost.Proto

a[b] + (c * d)

16

(+)

(*)

c d

([])

a b

構文木 (Syntax Tree) で表すと:

Page 24: Boost.勉強会#4 Boost.Proto

a[b] + (c * d)

17

expr<tag::plus, list2< expr<tag::subscript, list2<, expr<tag::terminal, term<int>, 0>&, expr<tag::terminal, term<int>, 0>& >, 2 > const&, expr<tag::multiplies, list2< expr<tag::terminal, term<int> 0>&, expr<tag::terminal, term<int> 0>& >, 2 > const& >, 2> const

Page 25: Boost.勉強会#4 Boost.Proto

a[b] + (c * d)

18

expr<tag::plus, list2< expr<tag::subscript, list2<, expr<tag::terminal, term<int>, 0>&, expr<tag::terminal, term<int>, 0>& >, 2 > const&, expr<tag::multiplies, list2< expr<tag::terminal, term<int> 0>&, expr<tag::terminal, term<int> 0>& >, 2 > const& >, 2> const

式を表す型 exprns_::expr

Page 26: Boost.勉強会#4 Boost.Proto

a[b] + (c * d)

19

expr<tag::plus, list2< expr<tag::subscript, list2<, expr<tag::terminal, term<int>, 0>&, expr<tag::terminal, term<int>, 0>& >, 2 > const&, expr<tag::multiplies, list2< expr<tag::terminal, term<int> 0>&, expr<tag::terminal, term<int> 0>& >, 2 > const& >, 2> const

式の種類を表すタグplus → +

multiplies → *subscript → []

など…

Page 27: Boost.勉強会#4 Boost.Proto

a[b] + (c * d)

20

expr<tag::plus, list2< expr<tag::subscript, list2<, expr<tag::terminal, term<int>, 0>&, expr<tag::terminal, term<int>, 0>& >, 2 > const&, expr<tag::multiplies, list2< expr<tag::terminal, term<int> 0>&, expr<tag::terminal, term<int> 0>& >, 2 > const& >, 2> const

子ノードを表す argsns_::listN

Page 28: Boost.勉強会#4 Boost.Proto

a[b] + (c * d)

21

expr<tag::plus, list2< expr<tag::subscript, list2<, expr<tag::terminal, term<int>, 0>&, expr<tag::terminal, term<int>, 0>& >, 2 > const&, expr<tag::multiplies, list2< expr<tag::terminal, term<int> 0>&, expr<tag::terminal, term<int> 0>& >, 2 > const& >, 2> const

終端記号を表す型

exprns_::term

Page 29: Boost.勉強会#4 Boost.Proto

a[b] + (c * d)

22

expr<tag::plus, list2< expr<tag::subscript, list2<, expr<tag::terminal, term<int>, 0>&, expr<tag::terminal, term<int>, 0>& >, 2 > const&, expr<tag::multiplies, list2< expr<tag::terminal, term<int> 0>&, expr<tag::terminal, term<int> 0>& >, 2 > const& >, 2> const

Page 30: Boost.勉強会#4 Boost.Proto

とりあえず使ってみる

23

default_context const ctx;std::cout << eval(lit(1) + 2 + 3, ctx) << std::endl;

コード:

実行結果:

6

Page 31: Boost.勉強会#4 Boost.Proto

24

とりあえず使ってみる

default_context const ctx;std::cout << eval(lit(1) + 2 + 3, ctx) << std::endl;

コード:

この式を、このコンテキストで評価する。

Page 32: Boost.勉強会#4 Boost.Proto

とりあえず使ってみる

25

式をどのように評価するかは、コンテキストが知っている。

default_context → C++の標準セマンティックnull_context → 何もしない

Page 33: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

•x + y という式を x - y というセマンティックで評価するコンテキストを作る

•話を簡単にするために、int型以外の終端記号と + 以外の演算子の挙動は定義しない

•→ コンパイルエラー

26

Page 34: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

27

struct my_context { template < class Expr, class Enable = void > struct eval;};

eval時にmy_context::eval<Expr>()(expr, ctx)の形で呼ばれる

Page 35: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

27

struct my_context { template < class Expr, class Enable = void > struct eval;};

eval時にmy_context::eval<Expr>()(expr, ctx)の形で呼ばれる

SFINAE用。なくても構わない。

Page 36: Boost.勉強会#4 Boost.Proto

SFINAE

• SFINAE (すふぃねー?)

• Substitution Failure Is Not An Error

•置き換え失敗はエラーに非ず

• boost::enable_ifなど

•template <class T>typename enable_if<is_const<T>>::type foo();

• SFINAEを用いて eval を分岐する。

28

Page 37: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

29

template <class Expr>struct eval< Expr, typename boost::enable_if< matches<Expr, terminal<int>> >::type> { typedef int result_type;

result_type operator ()(Expr& e, my_context const&) const { return value(e); }}

Page 38: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

30

template <class Expr>struct eval< Expr, typename boost::enable_if< matches<Expr, terminal<int>> >::type> { typedef int result_type;

result_type operator ()(Expr& e, my_context const&) const { return value(e); }}

proto式パターンマッチ:

Expr が terminal<int> にマッチするならば、メタ true

Page 39: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

31

template <class Expr>struct eval< Expr, typename boost::enable_if< matches<Expr, terminal<int>> >::type> { typedef int result_type;

result_type operator ()(Expr& e, my_context const&) const { return value(e); }}

評価した結果の型。C++0xならdecltypeで書ける。

Page 40: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

32

template <class Expr>struct eval< Expr, typename boost::enable_if< matches<Expr, terminal<int>> >::type> { typedef int result_type;

result_type operator ()(Expr& e, my_context const&) const { return value(e); }}

終端記号の値を取る

Page 41: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

33

template <class Expr>struct eval< Expr, typename boost::enable_if< matches<Expr, terminal<int>> >::type> { typedef int result_type;

result_type operator ()(Expr& e, my_context const&) const { return value(e); }}

Page 42: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

34

template <class Expr>struct eval< Expr, typename boost::enable_if< matches<Expr, plus<_, _>> >::type> { typedef int result_type;

result_type operator ()(Expr& e, my_context const& ctx) const { return proto::eval(left(e), ctx) - proto::eval(right(e), ctx); }}

Page 43: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

35

template <class Expr>struct eval< Expr, typename boost::enable_if< matches<Expr, plus<_, _>> >::type> { typedef int result_type;

result_type operator ()(Expr& e, my_context const& ctx) const { return proto::eval(left(e), ctx) - proto::eval(right(e), ctx); }}

_ は何にでもマッチする(wildcard)

Page 44: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

36

template <class Expr>struct eval< Expr, typename boost::enable_if< matches<Expr, plus<_, _>> >::type> { typedef int result_type;

result_type operator ()(Expr& e, my_context const& ctx) const { return proto::eval(left(e), ctx) - proto::eval(right(e), ctx); }}

left: 1番目の子ノードを得るright: 2番目の子ノードを得る

Page 45: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

37

template <class Expr>struct eval< Expr, typename boost::enable_if< matches<Expr, plus<_, _>> >::type> { typedef int result_type;

result_type operator ()(Expr& e, my_context const& ctx) const { return proto::eval(left(e), ctx) - proto::eval(right(e), ctx); }}

足すのではなく、引く

Page 46: Boost.勉強会#4 Boost.Proto

+ を - とするコンテキスト

38

template <class Expr>struct eval< Expr, typename boost::enable_if< matches<Expr, plus<_, _>> >::type> { typedef int result_type;

result_type operator ()(Expr& e, my_context const& ctx) const { return proto::eval(left(e), ctx) - proto::eval(right(e), ctx); }}

Page 47: Boost.勉強会#4 Boost.Proto

とりあえず使ってみる その2

39

my_context const ctx;std::cout << eval(lit(1) + 2 + 3, ctx) << std::endl;

コード:

実行結果:

-4

Page 48: Boost.勉強会#4 Boost.Proto

実行時/コンパイル時

•実行時関数:

• proto::left, proto::right

•コンパイル時の返り値型:

• proto::result_of::left, proto::result_of::right

•C++0xでは若干いらない子

40

Page 49: Boost.勉強会#4 Boost.Proto

その他の拡張•Context

•評価に関する情報の提供

•Domain

•式の生成手段の提供

• Extends

•式を表す型を自分で提供する

•Grammer

•文法を定義する。演算子オーバーロードの制御41

Page 50: Boost.勉強会#4 Boost.Proto

その他の拡張

42

入りきらないので参考文献:

1.User’s Guide

http://www.boost.org/doc/libs/1_46_0/doc/html/proto/users_guide.html

2. 自ブログ (C++ Advent Calender JP 2010; 16日目)

http://d.hatena.ne.jp/fjnl/20101222/

Page 51: Boost.勉強会#4 Boost.Proto

前半.end();

後半.begin();

43

Page 52: Boost.勉強会#4 Boost.Proto

Proto を数値計算に使う

• ET と数値計算は相性がいい

•「アルゴリズム」と「計算実装」を分離できる

•組み合わせの爆発を抑制

•見た目が良い (+ が加算を表す)

• (僕のやっている分野では)

単純な計算の組み合わせで表現できる

• Basic Linear Algebra Subprograms (BLAS)

44

Page 53: Boost.勉強会#4 Boost.Proto

Boost.uBLAS ではだめなのか

• Boost.uBLAS は可読性を重視している

• Boost.uBLAS は遅い

• Boost.uBLAS は拡張できない

45

Page 54: Boost.勉強会#4 Boost.Proto

Boost.uBLAS ではだめなのか

•アルゴリズムは CPU, GPU 共通

•コードを共有したい→バグが減る

•計算実装は CPU と GPU で異なり、内部実装が多種多様

•例:

•密行列の実装、疎行列の実装

• CPU: オリジナル, ATLAS, GotoBLAS, OpenCL

• GPU: オリジナル, CUBLAS, OpenCL

46

Page 55: Boost.勉強会#4 Boost.Proto

ET → 関数呼び出し列

47

Backend::scalar a;Backend::vector b, x, y;y = a * x + b;

Backend::eval< multiply, scalar, vector>()(y, a, x);Backend::eval< plus, vector, vector>()(y, y, b);

Page 56: Boost.勉強会#4 Boost.Proto

最適化

48

[a * x + y]plus<multiply<scalar, vector>, vector>

axpy<scalar, vector, vector>

積和演算の最適化をコンパイル時に行う。積和演算を一気に、かつ高速に行なえる

アーキテクチャが存在する。(Cell, GPU など)

Page 57: Boost.勉強会#4 Boost.Proto

49

ご清聴ありがとうございました。

そして

質疑応答