Document

POPL 2005 報告
報告者: 前田俊行
はじめに
• 法律上の請求の原因の種類を問わず、報告者
は、本報告の使用若しくは使用不能またはサ
ポートサービスの提供若しくは提供不能から生じ
る一切の損害 (逸失利益、機密情報若しくはそ
の他の情報の喪失、事業の中断、人身障害、プ
ライバシーの喪失、誠実または合理的な注意義
務を含めた義務の不履行、過失、 またはその他
の金銭的損失を含みますがこれらに限定されま
せん) に関して一切責任を負いません。
Invited Talk:
Interpreting the Data
Rob Pike
(Google)
一言でいうと、このお話は
• Map & Reduce は素晴らしいという宣伝
– Map & Reduce : Google の開発者等が
Google のデータベースにアクセスするために
日常的に使っているらしい言語
一目でわかる Map & Reduce
proto "document.proto"
max_pagerank_url:
table maximum(1) [domain: string] of url: string
weight pagerank: int;
doc: Document = input;
url: string = doc.url;
emit max_pagerank_url[domain(url)] <- url
weight doc.pagerank;
一目でわかる Map & Reduce
proto "querylog.proto"
static RESOLUTION: int = 60;
# in minutes
log_record: QueryLogProto = input;
query: string = log_record.query;
datum: table sum[t: time][lat: int][lon: int] of int;
loc: location = locationinfo(log_record.ip);
if (def(loc)) {
t: time = log_record.time_usec;
m: int = minutesof(t);
m = m - m % RESOLUTION;
t = trunctohour(t) + time(m * int(MINUTE));
emit datum[t][int(loc.lat)][int(loc.lon)] <- 1;
}
Rob Pike 氏よりのお言葉
• Good
– make it easier to express yourself
• Better
– hide stuff you don’t care about
• Best
– hide stuff you do care about
• Give the language a purpose
A Simple Typed
Intermediate Language
for Object-Oriented Languages
J. Chen and D. Tardi
(Microsoft Research)
一言でいうと、この論文は
• オブジェクト指向言語のための
中間言語 (LILc) を提案する
– LILc = Low-level Intermediate Language
with Classes
何がうれしいのか?
• オブジェクト指向言語を
型情報を保存したまま
コンパイルできるようになる
– 型情報を保存することの利点
–
–
–
–
コンパイラのデバッグに使える
最適化に使える
プログラムの安全性証明に使える
etc.
» (TAL のように)
既存研究は?
• ある、が
– 型システムが非常に複雑である
• 再帰型や継承の扱いが複雑になる
– 安易にやると、型チェックが決定不能になる
– 汎用的でない
• 様々な言語機能をカバーできない
• 様々なコンパイル手法をカバーできない
等の理由により、流行していない
LILc の特徴
• 型システムが
– シンプル
• コンパイラ書きにも理解できる(?)
– 汎用的
• 様々な言語機能を表現できる
• 様々なコンパイル手法が利用できる(?)
• 型チェックが決定可能
LILcのアプローチ
• 「クラス」を「名前」と「レコード」に分ける
• 「名前」
: クラスの名前
• 「レコード」 : クラスの具体的なデータ表現
• 「名前」の親子関係と
「レコード」の親子関係を分ける
• 「名前」の親子関係: subclassing
• 「レコード」の親子関係: subtyping
• クラス間の継承関係を
subclassing だけで表現する
名前
A
subclass
= 継承
subtype
レコード
B
LILc で表現できること(の一部)
• クラス間の継承関係
• ダウンキャスト
(例) Object obj = “Test”;
String str = (String)obj;
• Covariant array
(例) Integer[] ints = new Integer[10];
Object[] objs = ints;
objs[0] = “Hello, World!”;
A Bisimulation for
Type Abstraction and Recursion
E. Sumii and B. C. Pierce
(University of Pennsylvania)
一言でいうと、この論文は
• 2つのプログラム(この論文ではλ-calculus) が
等価であることを証明するための
手法を提案する
– 等価であること =
あらゆる実行コンテキストで同じ振舞をすること
– この論文の提案する手法
• Bisimulation による方法
何がうれしいのか?
• コンパイラの最適化が正しいかどうか
検証できる
• 同じインターフェイスを持った
2つのモジュールが本当に等しいか、
つまり、どちらのモジュールを使っても
結果が変わらないかを検証できる
• etc…
既存研究は?
• ある、が上手く使えない
– Logical Relation による方法
• 問題: 再帰関数や再帰型を扱うと複雑になる
– (従来の) Bisimulation による方法
• 問題:
– 抽象型 (existential型) に応用できない
– 完全でない
» 本当は等価なプログラムを異なると判断する場合がある
この論文の手法の特徴
• Bisimulation を
等価なプログラムの関係ではなく、
等価なプログラムの関係の集合と考える
この論文の方式
従来の方式
抽象型の
ための何か1
P2
P1
P5
P3
P4
何か2
P1
P6
P2
P6
P4
P3
P5
従来の手法でなぜ
抽象型が扱えないのか
• 抽象型の値に関する情報を忘れてしまうから
(例)
M = pack int, <1,λx:int.x=0> as τ
M’= pack bool, <true,λx:bool.¬x> as τ
( τ= ∃α.α×(α→bool) )
λx:bool.¬x:
α→bool
M
M’
1:α
true:α
λx:int.x=0:
α→bool
この関数が取れる引数が
true:αだけということがわからない
この関数が取れる引数が
1:αだけということがわからない
この論文の手法
• 抽象型の値に関する情報も追跡する
(例)
α: int, bool
λx:bool.¬x:
α→bool
M
M’
1:α
true:α
λx:int.x=0:
α→bool
この関数が取れる引数が
true:αだけということがわかる
この関数が取れる引数が
1:αだけということがわかる
この論文の手法の性質
• 抽象型も扱える
• 健全かつ完全である
• シンプルである
– 従来の手法と比べて
Mutatis Mutandis:
Safe and Predictable
Dynamic Software Updating
G. Stoyle (University of Cambridge),
M. Hicks (University of Maryland),
G. Bierman (Microsoft Research),
P. Sewell (University of Cambridge) and
I. Neamtiu (University of Maryland)
一言でいうと、この論文は
• 実行時に動的にプログラムを更新できる言語
(Proteus) を提案する
– Proteus の特徴
• 安全
• 柔軟
• 予測可能
何がうれしいのか?
• プログラムを停止させることなく
そのプログラムを更新することができる
– (例) Windows を停止させることなく
Windows Update する
この論文で扱う更新の種類
• 名前付き型の更新・追加
• トップレベル関数・変数の更新・追加
名前付き型の例
type A {
int a;
};
C の構造体や
Caml の type n = …
この論文の手法で実現できる
実行時更新の例
type A {
int(int) a;
int b;
};
type A {
int a;
};
更新
A M(A a1)
{
A a2;
a2.a = a1.a + 1;
return a2;
}
(注) 本当は古い型Aの値から新しい型Aの値
への変換関数が必要だがここでは省略
A M(A a1)
{
A a2;
a2.a = a1.a;
a2.b = a1.a(a1.b);
return a2;
}
実行時更新の難しいところ
• 更新するタイミング
– 更新しようとしている型の値を
プログラムが正に操作しようとしていたら困る
更新してはいけないタイミングの例
type A {
type A {
int a; 更新したい
int(int) a;
};
int b;
};
A M(A a1)
{
A a2;
a2.a = a1.a + 1;
return a2;
}
このタイミングで
更新されると
あぶない!
この論文の手法
• 名前付き型の値を利用する式全てに
注釈を付ける
– 注釈の種類は2つ
• abs : 型の名前だけ分かればよい式に付ける
• con : 型の中身が分からなければならない式に付ける
• 安全に更新できる箇所に印(‘update’)を付ける
– 安全に更新できる箇所 = それ以降 con が存在しない箇所
• これらの注釈や印は全て
型推論によって自動的に付けられる
注釈や印の例
A M(A a1)
注釈を付ける A M(A a1)
{
{
A a2;
A a2;
(conAa2).a =
a2.a = a1.a + 1;
(conAa1).a + 1;
return a2;
update;
}
return (absAa2);
ここなら型 A を更新しても安全!
}
(型 A の中身を使わないから)
From Sequential Programs to
Multi-Tier Applications by
Program Transformations
M. Newbauer and P. Thiemann
..
(Universitat Freiburg)
一言でいうと、この論文は
• 自然な形で書かれたプログラムを
Multi-Tier な形に自動的に変換する
手法を提案する
– Multi-Tier なアプリケーションの例
• Web アプリケーション
– 主に3つのtier
» クライアントのブラウザ
» アプリケーションサーバ
» データベースサーバ
何がうれしいのか?
• Multi-Tier なアプリケーションを
簡単に書けるようになる
– Multi-Tier なアプリケーションの作成は
複雑で難しい
• 複数のマシンの連携
• 非同期性
(例) 以下のプログラムを
Multi-Tier な形に変換する
void show_messages() {
string query = GUI_get_query();
string[] messages = DB_query(query);
GUI_show_messages(messages);
}
手順1: 関数や値に注釈をつける
void show_messages() {
C
string query = GUI_get_query();
string[] messages = DB_query(query);
GUI_show_messages(messages);S
C
}
C
クライアント
S
サーバー
手順2: 注釈が衝突する場所に
‘trans’ を入れる
void show_messages() {
C
string query = GUI_get_query();
query = trans[C->S] query; S
string[] messages = DB_query(query);
messages = trans[S->C] messages;
GUI_show_messages(messages);
C
}
trans[A->B] : 場所Aから場所Bへデータを移す
手順3: プログラムを分割する
S
void show_messages() {
string query = recv();
string[] messages = DB_query(query);
send(messages);
}
C
void show_messages() {
string query = GUI_get_query();
send(query);
connectや listen
string[] messages = recv();
などは後述
GUI_show_messages(messages);
}
ここまでのやり方の問題
• 効率が良くない場合がある
– ‘trans’ ごとにコネクションを張る必要がある
S
open
close
open
close
void show_messages(Messages i) {
bool b = i.hasNext();
b = trans[S->C] b;
if (b) {
string message = i.next();
message = trans[S->C] message;
GUI_show_message(message);
C
show_messages(i);
}
}
この論文の提案する解決方法
• コネクションのスコープをできるだけ大きくする
open
S
void show_messages(Messages i) {
bool b = i.hasNext();
b = trans[S->C] b;
if (b) {
string message = i.next();
message = trans[S->C] message;
GUI_show_message(message);
C
show_messages(i);
}
close }
最適化の結果
C
void show_messages(Channel chan) {
bool b = recv(chan);
if (b) {
string message = recv(chan);
GUI_show_message(message);
show_messages(chan);
}
}
S
void show_messages(Messages i, Channel chan) {
bool b = i.hasNext();
send(chan, b);
if (b) {
string message = i.next();
send(chan, message);
show_messages(i, chan);
}
}
最適化の結果、
connectや listen
などはこの関数内で
する必要はないことが
分かった
Invited Talk:
How should we program
graphics hardware?
P. Hanrahan
(Stanford University)
一言でいうと、このお話は
• Graphics ハードウェアを計算に使いましょう
という呼びかけ
– 理由: CPU よりも GPU の方が性能がいいから
CPU と GPU の性能比較
出典:
Stream Programming Environments,
P. Hanrahan, GP^2 Workshop, 2004
Graphics ハードウェアの特徴
• 並列度が高い
出典:
Stream Programming Environments,
P. Hanrahan, GP^2 Workshop, 2004
GPU の並列処理方式
• ストリーム・アーキテクチャ
Input
カーネル
Output
カーネル
カーネル
Input
カーネル
カーネル
Output
カーネル: 小さなプログラム
ストリーム: データの流れ
では、その並列性を
上手く利用するためには?
• プログラミング言語のレベルで
ストリーム・アーキテクチャを
サポートすればよい
– この人達の提案する言語: Brook
一目で分かる Brook
kernel void foo(float a<>, float b<>,
output float result<>)
{
result = a + b;
}
void reduce sum(float a<>,
reduce float result<>)
{
result = result + a;
}