狠狠撸

狠狠撸Share a Scribd company logo
OCamlのアセンブラを
読む話
第二回惭尝勉强会
@no_maddo
わたしは誰
? インターネットの闇@no_maddo
? コンパイラが大好き
? コンパイラでコンパイラが食える
おことわり
イカ
楽しいです
残の行
アジェンダ
? OCamlの吐くx86アセンブラを読んで、
コンパイラの気持ちになるですよ
– 64bitのことしか気にしないリッチトーク
– 結論ありません
– OCaml 4.05.0, -O3, -unsafeでコンパイル
– 対象:初心者向け
? コンパイラ初心者
? とにかくアセンブラが読みたいマン
? 普通の話しかしません
OCamlが吐くアセンブラの注意
? 1ファイルで1つのモジュールを表す
– モジュールを作るための実行コードが作られる
? モジュール名でsuffix、アルファ変換されてる
– なぜだかわかりますね?
整数演算
let add1 x = x + 1 addq $2, %rax
ret
let add2 x = x + 2 addq $4, %rax
ret
tag bit
? GCのために値にtagを付けている
– intなら最下位bitが常に1
– pointerなら常に0
? Major GCではMark and Sweepをやるため
? 64bitのIntがほしいときはInt64がある
– allocされたナマの64bit int......
https://realworldocaml.org/v1/en/html/memory-representation-of-values.html
float型 1
let fadd1 x = x +. 1.0
subq $8, %rsp
.L100:
movq %rax, %rbx
.L101:
subq $16, %r15
movq caml_young_limit@GOTPCREL(%rip), %rax
cmpq (%rax), %r15
jb .L102
leaq 8(%r15), %rax
movq $1277, -8(%rax)
movsd .L104(%rip), %xmm0
addsd (%rbx), %xmm0
movsd %xmm0, (%rax)
addq $8, %rsp
.L102:
call caml_call_gc@PLT
.L103:
jmp .L101
なぜポインタ
? 疑問:float -> floatなら引数をunboxedでとっ
ても良いのでは???
? 高階関数との兼ね合いで1ワードに揃ってな
ければならない(boxed, uniform)
– 高階関数内で呼び出ししたときに使うレジスタ
float型 2
let fadd1_arr a x =
a.(0) <- x +. 1.0
movsd .L104(%rip), %xmm0
addsd (%rbx), %xmm0
movsd %xmm0, (%rax)
movq $1, %rax
ret
allocが不必要な場合には確保しない
※ -unsafeつきでコンパイル
一旦まとめ
? 整数とポインタを区別するタグがある
– GCとの兼ね合い
? float型の値は関数を経由するときに
メモリ確保される
– 多相関数との兼ね合い
for式とarray
? OCamlのfor式はfortranみたい
– for i = e1 to e2 do e3 done
– ループの入り口で回転数が確定する!
? このあたり最適化が弱い
for式 1
let itof = float_of_int
let f a b =
for i = 0 to 100 do
a.(i) <- b.(i) +. itof i
done
.L102:
movq $1, %rdi
cmpq $201, %rdi
jg .L100
.L101:
movq %rdi, %rsi
sarq $1, %rsi
cvtsi2sdq %rsi, %xmm0
addsd -4(%rbx,%rdi,4), %xmm0
movsd %xmm0, -4(%rax,%rdi,4)
movq %rdi, %rsi
addq $2, %rdi
cmpq $201, %rsi
jne .L101
.L100:
movq $1, %rax
ret
無駄
0をセット
右シフト
タグを外す
手で最適化
.L102:
movq $0, %rdi
.L101:
cvtsi2sdq %rdi, %xmm0
addsd 0(%rbx,%rdi,4), %xmm0
movsd %xmm0, 0(%rax,%rdi,4)
addq $1, %rdi
cmpq $100, %rsi
jne .L101
.L100:
movq $1, %rax
ret
.L102:
movq $1, %rdi
cmpq $201, %rdi
jg .L100
.L101:
movq %rdi, %rsi
sarq $1, %rsi
cvtsi2sdq %rsi, %xmm0
addsd -4(%rbx,%rdi,4), %xmm0
movsd %xmm0, -4(%rax,%rdi,4)
movq %rdi, %rsi
addq $2, %rdi
cmpq $201, %rsi
jne .L101
.L100:
movq $1, %rax
ret
?caml int -> raw intの最適化
?不要分岐の削除
ちなみにgcc –O2
void f (double a[],
double b[]) {
for (int i = 0; i < 100; i++)
a[i] = b[i] + (double) i;
}
f:
.LFB0:
xorl %eax, %eax
.L2:
pxor %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
addsd (%rsi,%rax,8), %xmm0
movsd %xmm0, (%rdi,%rax,8)
addq $1, %rax
cmpq $100, %rax
jne .L2
rep ret
for式 2
let itof = float_of_int
let f a b =
for i = 0 to 50 do
a.(i) <- b.(i) +. itof (i * 2);
a.(i+1) <-
b.(i+1) +. itof (i * 2 + 1);
done
.L101:
leaq -1(%rdi,%rdi), %rsi
sarq $1, %rsi
cvtsi2sdq %rsi, %xmm0
addsd -4(%rbx,%rdi,4), %xmm0
movsd %xmm0, -4(%rax,%rdi,4)
cvtsi2sdq %rdi, %xmm0
addsd 4(%rbx,%rdi,4), %xmm0
movsd %xmm0, 4(%rax,%rdi,4)
movq %rdi, %rsi
addq $2, %rdi
cmpq $101, %rsi
jne .L101
.L100:
movq $1, %rax
ret
camlFor2__f_1199:
.L102:
movq $1, %rdi
cmpq $101, %rdi
jg .L100
for式2の
gcc –O2
void f (double a[], double b[]){
for (int i = 0; i < 50; i++) {
a[i] = b[i] + i * 2;
a[i+1] = b[i+1] + (i + 1) * 2;
}}
.L2:
addsd -8(%rsi), %xmm0
addl $2, %eax
addq $8, %rsi
addq $8, %rdi
movsd %xmm0, -16(%rdi)
pxor %xmm0, %xmm0
movsd -8(%rsi), %xmm1
cvtsi2sd %eax, %xmm0
addsd %xmm0, %xmm1
movsd %xmm1, -8(%rdi)
cmpl $100, %eax
jne .L2
rep ret
f:
pxor %xmm0, %xmm0
xorl %eax, %eax
addq $8, %rsi
addq $8, %rdi
cvtsi2sd %eax, %xmm0
参考:Atom レーテンシ
? Silvermont アーキテクチャでのレーテンシ
? addsd
add + store, add + loadやっている命令
– xmm, xmm: 5
– xmm, mem: 5 (!?!?
? movsd
load, storeなども兼ねる
– xmm, xmm; xmm, mem; mem, xmm: 1
https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html
for式3
let f a b =
for i = 0 to 100 do
for j = 0 to 100 do
a.(i).(j) <- 1.0;
done
done
.L103:
movq -4(%rax,%rbx,4), %rsi
movsd .L105(%rip), %xmm0
movsd %xmm0, -4(%rsi,%rdi,4)
movq %rdi, %rsi
addq $2, %rdi
cmpq $201, %rsi
jne .L103
.L102:
movq %rbx, %rdi
addq $2, %rbx
cmpq $201, %rdi
jne .L101
.L100:
movq $1, %rax
.L104:
movq $1, %rbx
cmpq $201, %rbx
jg .L100
.L101:
movq $1, %rdi
cmpq $201, %rdi
jg .L102
for式3 gcc –O2
void f (double * a[],
double * b[]) {
for (int i = 0; i < 100; i++)
for (int j = 0; j < 100; j++)
a[i][j] = b[i][j] + i;
}
.L3:
movsd (%rdx,%rax), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rcx,%rax)
addq $8, %rax
cmpq $800, %rax
jne .L3
addq $1, %r8
cmpq $100, %r8
jne .L2
rep ret
xorl %r8d, %r8d
.L2:
pxor %xmm1, %xmm1
movq (%rdi,%r8,8), %rcx
movq (%rsi,%r8,8), %rdx
xorl %eax, %eax
cvtsi2sd %r8d, %xmm1
for式4 共通式
let f a b c =
for i = 0 to 100 do
a.(i) <- a.(i) +. c.(i);
b.(i) <- a.(i) +. c.(i);
done
.L101:
movsd -4(%rax,%rsi,4), %xmm0
addsd -4(%rdi,%rsi,4), %xmm0
movsd %xmm0, -4(%rax,%rsi,4)
movsd -4(%rax,%rsi,4), %xmm0
addsd -4(%rdi,%rsi,4), %xmm0
movsd %xmm0, -4(%rbx,%rsi,4)
movq %rsi, %rdx
addq $2, %rsi
cmpq $201, %rdx
jne .L101
.L100:
movq $1, %rax
ret
.L102:
movq $1, %rsi
cmpq $201, %rsi
jg .L100
for式4 gcc
void f (double a[],
double b[], double c[]) {
for (int i = 0; i < 100; i++) {
a[i] = a[i] + c[i];
b[i] = a[i] + c[i]; } }
f:
xorl %eax, %eax
.L2:
movsd (%rdi,%rax), %xmm0
addsd (%rdx,%rax), %xmm0
movsd %xmm0, (%rdi,%rax)
addsd (%rdx,%rax), %xmm0
movsd %xmm0, (%rsi,%rax)
addq $8, %rax
cmpq $800, %rax
jne .L2
rep ret
.L102:
movq $1, %rsi
cmpq $201, %rsi
jg .L100
SIMD化されてる
共通式の除去
for式5 共通式2
let f a b n =
for i = 0 to 100 do
a.(i) <- n +. 3.0;
b.(i) <- n +. 4.0;
done
f:
movsd .LC0(%rip), %xmm1
xorl %eax, %eax
addsd %xmm0, %xmm1
addsd .LC1(%rip), %xmm0
.L2:
movsd %xmm1, (%rdi,%rax)
movsd %xmm0, (%rsi,%rax)
addq $8, %rax
cmpq $800, %rax
jne .L2
rep ret
感想
? 想像したとおりの愚直なアセンブラが出る
? あんまり共通式とか取られない
? gccと比べて出来てない目立つ最適化
– 分岐の除去(!)
– 共通式
– ループアンローリング(-O3)
match1
let f = function
| x :: xs -> [x]
| [] -> [0]
.L102:
subq $24, %r15
movq caml_young_limit
@GOTPCREL(%rip), %rax
cmpq (%rax), %r15
jb .L103
leaq 8(%r15), %rax
movq $2048, -8(%rax)
movq (%rbx), %rbx
movq %rbx, (%rax)
movq $1, 8(%rax)
addq $8, %rsp
ret
subq $8, %rsp
.L101:
movq %rax, %rbx
cmpq $1, %rbx
je .L100
list1
let f x =
x :: x :: x :: []
movq $1, 8(%rax)
leaq 24(%rax), %rdi
movq $2048, -8(%rdi)
movq %rbx, (%rdi)
movq %rax, 8(%rdi)
addq $48, %rax
movq $2048, -8(%rax)
movq %rbx, (%rax)
movq %rdi, 8(%rax)
addq $8, %rsp
ret
.L102:
call caml_call_gc@PLT
.L103:
jmp .L101
subq $8, %rsp
.L100:
movq %rax, %rbx
.L101:
subq $72, %r15
movq caml_young_limit
@GOTPCREL(%rip), %rax
cmpq (%rax), %r15
jb .L102
leaq 8(%r15), %rax
movq $2048, -8(%rax)
movq %rbx, (%rax)
まとめ?
? 小さい関数のasmなら普通に読める
? OCamlコンパイラは最適化が足りない
– まぁGCのオーバーヘッドとか気にした方がいい
– 普通はあんまり気にならない
? ループの最内とかは気にしたほうが良い
? 数値を計算するときはfloatのmallocがきびしい
インライン展開が有効

More Related Content

What's hot (20)

第1回ROS勉強会発表資料 ROS+Gazeboではじめるロボットシミュレーション
第1回ROS勉強会発表資料 ROS+Gazeboではじめるロボットシミュレーション第1回ROS勉強会発表資料 ROS+Gazeboではじめるロボットシミュレーション
第1回ROS勉強会発表資料 ROS+Gazeboではじめるロボットシミュレーション
akio19937
?
笔测蚕迟ではじめる骋鲍滨プログラミング
笔测蚕迟ではじめる骋鲍滨プログラミング笔测蚕迟ではじめる骋鲍滨プログラミング
笔测蚕迟ではじめる骋鲍滨プログラミング
Ransui Iso
?
础奥厂からのメール送信
础奥厂からのメール送信础奥厂からのメール送信
础奥厂からのメール送信
Amazon Web Services Japan
?
笔测迟丑辞苍とパッケージングと私
笔测迟丑辞苍とパッケージングと私笔测迟丑辞苍とパッケージングと私
笔测迟丑辞苍とパッケージングと私
Atsushi Odagiri
?
Marp Tutorial
Marp TutorialMarp Tutorial
Marp Tutorial
Rui Watanabe
?
AWS Black Belt Online Seminar 2018 AWS上の位置情報
AWS Black Belt Online Seminar 2018 AWS上の位置情報AWS Black Belt Online Seminar 2018 AWS上の位置情報
AWS Black Belt Online Seminar 2018 AWS上の位置情報
Amazon Web Services Japan
?
AWS LambdaとDynamoDBがこんなにツライはずがない #ssmjp
AWS LambdaとDynamoDBがこんなにツライはずがない #ssmjpAWS LambdaとDynamoDBがこんなにツライはずがない #ssmjp
AWS LambdaとDynamoDBがこんなにツライはずがない #ssmjp
Masahiro NAKAYAMA
?
お前は PHP の歴史的な理由の数を覚えているのか
お前は PHP の歴史的な理由の数を覚えているのかお前は PHP の歴史的な理由の数を覚えているのか
お前は PHP の歴史的な理由の数を覚えているのか
Kousuke Ebihara
?
ここがつらいよWebRTC - WebRTC開発の落とし穴
ここがつらいよWebRTC - WebRTC開発の落とし穴ここがつらいよWebRTC - WebRTC開発の落とし穴
ここがつらいよWebRTC - WebRTC開発の落とし穴
mganeko
?
贵濒耻别苍迟诲のお勧めシステム构成パターン
贵濒耻别苍迟诲のお勧めシステム构成パターン贵濒耻别苍迟诲のお勧めシステム构成パターン
贵濒耻别苍迟诲のお勧めシステム构成パターン
Kentaro Yoshida
?
Azure Cosmos DB のキホンと使いドコロ
Azure Cosmos DB のキホンと使いドコロAzure Cosmos DB のキホンと使いドコロ
Azure Cosmos DB のキホンと使いドコロ
Kazuyuki Miyake
?
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
Fixstars Corporation
?
摆社内勉强会闭贰尝叠と础尝叠と数万スハ?イク负荷テスト
摆社内勉强会闭贰尝叠と础尝叠と数万スハ?イク负荷テスト摆社内勉强会闭贰尝叠と础尝叠と数万スハ?イク负荷テスト
摆社内勉强会闭贰尝叠と础尝叠と数万スハ?イク负荷テスト
Takahiro Moteki
?
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
NTT DATA Technology & Innovation
?
マイクロにしすぎた结果がこれだよ!
マイクロにしすぎた结果がこれだよ!マイクロにしすぎた结果がこれだよ!
マイクロにしすぎた结果がこれだよ!
mosa siru
?
これが颁补蝉蝉补苍诲谤补
これが颁补蝉蝉补苍诲谤补これが颁补蝉蝉补苍诲谤补
これが颁补蝉蝉补苍诲谤补
Takehiro Torigaki
?
尝颈苍耻虫にて复数のコマンドを并列実行(同时実行数の制限付き)
尝颈苍耻虫にて复数のコマンドを并列実行(同时実行数の制限付き)尝颈苍耻虫にて复数のコマンドを并列実行(同时実行数の制限付き)
尝颈苍耻虫にて复数のコマンドを并列実行(同时実行数の制限付き)
Hiro H.
?
ロードバランスへの长い道
ロードバランスへの长い道ロードバランスへの长い道
ロードバランスへの长い道
Jun Kato
?
PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門
泰 増田
?
竞プロで骋辞!
竞プロで骋辞!竞プロで骋辞!
竞プロで骋辞!
鈴木 セシル
?
第1回ROS勉強会発表資料 ROS+Gazeboではじめるロボットシミュレーション
第1回ROS勉強会発表資料 ROS+Gazeboではじめるロボットシミュレーション第1回ROS勉強会発表資料 ROS+Gazeboではじめるロボットシミュレーション
第1回ROS勉強会発表資料 ROS+Gazeboではじめるロボットシミュレーション
akio19937
?
笔测蚕迟ではじめる骋鲍滨プログラミング
笔测蚕迟ではじめる骋鲍滨プログラミング笔测蚕迟ではじめる骋鲍滨プログラミング
笔测蚕迟ではじめる骋鲍滨プログラミング
Ransui Iso
?
笔测迟丑辞苍とパッケージングと私
笔测迟丑辞苍とパッケージングと私笔测迟丑辞苍とパッケージングと私
笔测迟丑辞苍とパッケージングと私
Atsushi Odagiri
?
AWS Black Belt Online Seminar 2018 AWS上の位置情報
AWS Black Belt Online Seminar 2018 AWS上の位置情報AWS Black Belt Online Seminar 2018 AWS上の位置情報
AWS Black Belt Online Seminar 2018 AWS上の位置情報
Amazon Web Services Japan
?
AWS LambdaとDynamoDBがこんなにツライはずがない #ssmjp
AWS LambdaとDynamoDBがこんなにツライはずがない #ssmjpAWS LambdaとDynamoDBがこんなにツライはずがない #ssmjp
AWS LambdaとDynamoDBがこんなにツライはずがない #ssmjp
Masahiro NAKAYAMA
?
お前は PHP の歴史的な理由の数を覚えているのか
お前は PHP の歴史的な理由の数を覚えているのかお前は PHP の歴史的な理由の数を覚えているのか
お前は PHP の歴史的な理由の数を覚えているのか
Kousuke Ebihara
?
ここがつらいよWebRTC - WebRTC開発の落とし穴
ここがつらいよWebRTC - WebRTC開発の落とし穴ここがつらいよWebRTC - WebRTC開発の落とし穴
ここがつらいよWebRTC - WebRTC開発の落とし穴
mganeko
?
贵濒耻别苍迟诲のお勧めシステム构成パターン
贵濒耻别苍迟诲のお勧めシステム构成パターン贵濒耻别苍迟诲のお勧めシステム构成パターン
贵濒耻别苍迟诲のお勧めシステム构成パターン
Kentaro Yoshida
?
Azure Cosmos DB のキホンと使いドコロ
Azure Cosmos DB のキホンと使いドコロAzure Cosmos DB のキホンと使いドコロ
Azure Cosmos DB のキホンと使いドコロ
Kazuyuki Miyake
?
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
Fixstars Corporation
?
摆社内勉强会闭贰尝叠と础尝叠と数万スハ?イク负荷テスト
摆社内勉强会闭贰尝叠と础尝叠と数万スハ?イク负荷テスト摆社内勉强会闭贰尝叠と础尝叠と数万スハ?イク负荷テスト
摆社内勉强会闭贰尝叠と础尝叠と数万スハ?イク负荷テスト
Takahiro Moteki
?
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
NTT DATA Technology & Innovation
?
マイクロにしすぎた结果がこれだよ!
マイクロにしすぎた结果がこれだよ!マイクロにしすぎた结果がこれだよ!
マイクロにしすぎた结果がこれだよ!
mosa siru
?
これが颁补蝉蝉补苍诲谤补
これが颁补蝉蝉补苍诲谤补これが颁补蝉蝉补苍诲谤补
これが颁补蝉蝉补苍诲谤补
Takehiro Torigaki
?
尝颈苍耻虫にて复数のコマンドを并列実行(同时実行数の制限付き)
尝颈苍耻虫にて复数のコマンドを并列実行(同时実行数の制限付き)尝颈苍耻虫にて复数のコマンドを并列実行(同时実行数の制限付き)
尝颈苍耻虫にて复数のコマンドを并列実行(同时実行数の制限付き)
Hiro H.
?
ロードバランスへの长い道
ロードバランスへの长い道ロードバランスへの长い道
ロードバランスへの长い道
Jun Kato
?
PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門
泰 増田
?

Similar to 翱颁补尘濒のアセンブラを読む话 (20)

尝尝痴惭最适化のこつ
尝尝痴惭最适化のこつ尝尝痴惭最适化のこつ
尝尝痴惭最适化のこつ
MITSUNARI Shigeo
?
One - Common Lispでもワンライナーしたい
One - Common LispでもワンライナーしたいOne - Common Lispでもワンライナーしたい
One - Common Lispでもワンライナーしたい
t-sin
?
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1
Ransui Iso
?
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイル
なおき きしだ
?
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
Noritada Shimizu
?
as-5. サブルーチン呼び出しのメカニズム
as-5. サブルーチン呼び出しのメカニズムas-5. サブルーチン呼び出しのメカニズム
as-5. サブルーチン呼び出しのメカニズム
kunihikokaneko1
?
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
Nobuhisa Koizumi
?
HPC Phys-20201203
HPC Phys-20201203HPC Phys-20201203
HPC Phys-20201203
MITSUNARI Shigeo
?
统计をとって高速化する?厂肠补濒补开発
统计をとって高速化する?厂肠补濒补开発统计をとって高速化する?厂肠补濒补开発
统计をとって高速化する?厂肠补濒补开発
Mitsuki Ogasahara
?
统计をとって高速化する?厂肠补濒补开発 by CyberZ,Inc.
统计をとって高速化する?厂肠补濒补开発 by CyberZ,Inc.统计をとって高速化する?厂肠补濒补开発 by CyberZ,Inc.
统计をとって高速化する?厂肠补濒补开発 by CyberZ,Inc.
scalaconfjp
?
2017-12-04 Linuxの基本構造とBashでの扱い方
2017-12-04 Linuxの基本構造とBashでの扱い方2017-12-04 Linuxの基本構造とBashでの扱い方
2017-12-04 Linuxの基本構造とBashでの扱い方
浩平 渡邉
?
メタメタプログラミング搁耻产测
メタメタプログラミング搁耻产测メタメタプログラミング搁耻产测
メタメタプログラミング搁耻产测
emasaka
?
Intro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみたIntro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみた
MITSUNARI Shigeo
?
つくってあそぼ ラムダ計算インタプリタ
つくってあそぼ ラムダ計算インタプリタつくってあそぼ ラムダ計算インタプリタ
つくってあそぼ ラムダ計算インタプリタ
京大 マイコンクラブ
?
CRF を使った Web 本文抽出
CRF を使った Web 本文抽出CRF を使った Web 本文抽出
CRF を使った Web 本文抽出
Shuyo Nakatani
?
毎秒2000搁别辩耻别蝉迟を捌く笔别谤濒製颁惭厂の内部构造(顿别产颈补苍サーバ1台にて)
毎秒2000搁别辩耻别蝉迟を捌く笔别谤濒製颁惭厂の内部构造(顿别产颈补苍サーバ1台にて)毎秒2000搁别辩耻别蝉迟を捌く笔别谤濒製颁惭厂の内部构造(顿别产颈补苍サーバ1台にて)
毎秒2000搁别辩耻别蝉迟を捌く笔别谤濒製颁惭厂の内部构造(顿别产颈补苍サーバ1台にて)
nabe-abk
?
debugging server with strace
debugging server with stracedebugging server with strace
debugging server with strace
Yoshinari Takaoka
?
尝尝痴惭最适化のこつ
尝尝痴惭最适化のこつ尝尝痴惭最适化のこつ
尝尝痴惭最适化のこつ
MITSUNARI Shigeo
?
One - Common Lispでもワンライナーしたい
One - Common LispでもワンライナーしたいOne - Common Lispでもワンライナーしたい
One - Common Lispでもワンライナーしたい
t-sin
?
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1
Ransui Iso
?
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイル
なおき きしだ
?
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
Noritada Shimizu
?
as-5. サブルーチン呼び出しのメカニズム
as-5. サブルーチン呼び出しのメカニズムas-5. サブルーチン呼び出しのメカニズム
as-5. サブルーチン呼び出しのメカニズム
kunihikokaneko1
?
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
Nobuhisa Koizumi
?
统计をとって高速化する?厂肠补濒补开発
统计をとって高速化する?厂肠补濒补开発统计をとって高速化する?厂肠补濒补开発
统计をとって高速化する?厂肠补濒补开発
Mitsuki Ogasahara
?
统计をとって高速化する?厂肠补濒补开発 by CyberZ,Inc.
统计をとって高速化する?厂肠补濒补开発 by CyberZ,Inc.统计をとって高速化する?厂肠补濒补开発 by CyberZ,Inc.
统计をとって高速化する?厂肠补濒补开発 by CyberZ,Inc.
scalaconfjp
?
2017-12-04 Linuxの基本構造とBashでの扱い方
2017-12-04 Linuxの基本構造とBashでの扱い方2017-12-04 Linuxの基本構造とBashでの扱い方
2017-12-04 Linuxの基本構造とBashでの扱い方
浩平 渡邉
?
メタメタプログラミング搁耻产测
メタメタプログラミング搁耻产测メタメタプログラミング搁耻产测
メタメタプログラミング搁耻产测
emasaka
?
Intro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみたIntro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみた
MITSUNARI Shigeo
?
つくってあそぼ ラムダ計算インタプリタ
つくってあそぼ ラムダ計算インタプリタつくってあそぼ ラムダ計算インタプリタ
つくってあそぼ ラムダ計算インタプリタ
京大 マイコンクラブ
?
CRF を使った Web 本文抽出
CRF を使った Web 本文抽出CRF を使った Web 本文抽出
CRF を使った Web 本文抽出
Shuyo Nakatani
?
毎秒2000搁别辩耻别蝉迟を捌く笔别谤濒製颁惭厂の内部构造(顿别产颈补苍サーバ1台にて)
毎秒2000搁别辩耻别蝉迟を捌く笔别谤濒製颁惭厂の内部构造(顿别产颈补苍サーバ1台にて)毎秒2000搁别辩耻别蝉迟を捌く笔别谤濒製颁惭厂の内部构造(顿别产颈补苍サーバ1台にて)
毎秒2000搁别辩耻别蝉迟を捌く笔别谤濒製颁惭厂の内部构造(顿别产颈补苍サーバ1台にて)
nabe-abk
?

翱颁补尘濒のアセンブラを読む话

  • 4. アジェンダ ? OCamlの吐くx86アセンブラを読んで、 コンパイラの気持ちになるですよ – 64bitのことしか気にしないリッチトーク – 結論ありません – OCaml 4.05.0, -O3, -unsafeでコンパイル – 対象:初心者向け ? コンパイラ初心者 ? とにかくアセンブラが読みたいマン ? 普通の話しかしません
  • 6. 整数演算 let add1 x = x + 1 addq $2, %rax ret let add2 x = x + 2 addq $4, %rax ret
  • 7. tag bit ? GCのために値にtagを付けている – intなら最下位bitが常に1 – pointerなら常に0 ? Major GCではMark and Sweepをやるため ? 64bitのIntがほしいときはInt64がある – allocされたナマの64bit int...... https://realworldocaml.org/v1/en/html/memory-representation-of-values.html
  • 8. float型 1 let fadd1 x = x +. 1.0 subq $8, %rsp .L100: movq %rax, %rbx .L101: subq $16, %r15 movq caml_young_limit@GOTPCREL(%rip), %rax cmpq (%rax), %r15 jb .L102 leaq 8(%r15), %rax movq $1277, -8(%rax) movsd .L104(%rip), %xmm0 addsd (%rbx), %xmm0 movsd %xmm0, (%rax) addq $8, %rsp .L102: call caml_call_gc@PLT .L103: jmp .L101
  • 9. なぜポインタ ? 疑問:float -> floatなら引数をunboxedでとっ ても良いのでは??? ? 高階関数との兼ね合いで1ワードに揃ってな ければならない(boxed, uniform) – 高階関数内で呼び出ししたときに使うレジスタ
  • 10. float型 2 let fadd1_arr a x = a.(0) <- x +. 1.0 movsd .L104(%rip), %xmm0 addsd (%rbx), %xmm0 movsd %xmm0, (%rax) movq $1, %rax ret allocが不必要な場合には確保しない ※ -unsafeつきでコンパイル
  • 11. 一旦まとめ ? 整数とポインタを区別するタグがある – GCとの兼ね合い ? float型の値は関数を経由するときに メモリ確保される – 多相関数との兼ね合い
  • 12. for式とarray ? OCamlのfor式はfortranみたい – for i = e1 to e2 do e3 done – ループの入り口で回転数が確定する! ? このあたり最適化が弱い
  • 13. for式 1 let itof = float_of_int let f a b = for i = 0 to 100 do a.(i) <- b.(i) +. itof i done .L102: movq $1, %rdi cmpq $201, %rdi jg .L100 .L101: movq %rdi, %rsi sarq $1, %rsi cvtsi2sdq %rsi, %xmm0 addsd -4(%rbx,%rdi,4), %xmm0 movsd %xmm0, -4(%rax,%rdi,4) movq %rdi, %rsi addq $2, %rdi cmpq $201, %rsi jne .L101 .L100: movq $1, %rax ret 無駄 0をセット 右シフト タグを外す
  • 14. 手で最適化 .L102: movq $0, %rdi .L101: cvtsi2sdq %rdi, %xmm0 addsd 0(%rbx,%rdi,4), %xmm0 movsd %xmm0, 0(%rax,%rdi,4) addq $1, %rdi cmpq $100, %rsi jne .L101 .L100: movq $1, %rax ret .L102: movq $1, %rdi cmpq $201, %rdi jg .L100 .L101: movq %rdi, %rsi sarq $1, %rsi cvtsi2sdq %rsi, %xmm0 addsd -4(%rbx,%rdi,4), %xmm0 movsd %xmm0, -4(%rax,%rdi,4) movq %rdi, %rsi addq $2, %rdi cmpq $201, %rsi jne .L101 .L100: movq $1, %rax ret ?caml int -> raw intの最適化 ?不要分岐の削除
  • 15. ちなみにgcc –O2 void f (double a[], double b[]) { for (int i = 0; i < 100; i++) a[i] = b[i] + (double) i; } f: .LFB0: xorl %eax, %eax .L2: pxor %xmm0, %xmm0 cvtsi2sd %eax, %xmm0 addsd (%rsi,%rax,8), %xmm0 movsd %xmm0, (%rdi,%rax,8) addq $1, %rax cmpq $100, %rax jne .L2 rep ret
  • 16. for式 2 let itof = float_of_int let f a b = for i = 0 to 50 do a.(i) <- b.(i) +. itof (i * 2); a.(i+1) <- b.(i+1) +. itof (i * 2 + 1); done .L101: leaq -1(%rdi,%rdi), %rsi sarq $1, %rsi cvtsi2sdq %rsi, %xmm0 addsd -4(%rbx,%rdi,4), %xmm0 movsd %xmm0, -4(%rax,%rdi,4) cvtsi2sdq %rdi, %xmm0 addsd 4(%rbx,%rdi,4), %xmm0 movsd %xmm0, 4(%rax,%rdi,4) movq %rdi, %rsi addq $2, %rdi cmpq $101, %rsi jne .L101 .L100: movq $1, %rax ret camlFor2__f_1199: .L102: movq $1, %rdi cmpq $101, %rdi jg .L100
  • 17. for式2の gcc –O2 void f (double a[], double b[]){ for (int i = 0; i < 50; i++) { a[i] = b[i] + i * 2; a[i+1] = b[i+1] + (i + 1) * 2; }} .L2: addsd -8(%rsi), %xmm0 addl $2, %eax addq $8, %rsi addq $8, %rdi movsd %xmm0, -16(%rdi) pxor %xmm0, %xmm0 movsd -8(%rsi), %xmm1 cvtsi2sd %eax, %xmm0 addsd %xmm0, %xmm1 movsd %xmm1, -8(%rdi) cmpl $100, %eax jne .L2 rep ret f: pxor %xmm0, %xmm0 xorl %eax, %eax addq $8, %rsi addq $8, %rdi cvtsi2sd %eax, %xmm0
  • 18. 参考:Atom レーテンシ ? Silvermont アーキテクチャでのレーテンシ ? addsd add + store, add + loadやっている命令 – xmm, xmm: 5 – xmm, mem: 5 (!?!? ? movsd load, storeなども兼ねる – xmm, xmm; xmm, mem; mem, xmm: 1 https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html
  • 19. for式3 let f a b = for i = 0 to 100 do for j = 0 to 100 do a.(i).(j) <- 1.0; done done .L103: movq -4(%rax,%rbx,4), %rsi movsd .L105(%rip), %xmm0 movsd %xmm0, -4(%rsi,%rdi,4) movq %rdi, %rsi addq $2, %rdi cmpq $201, %rsi jne .L103 .L102: movq %rbx, %rdi addq $2, %rbx cmpq $201, %rdi jne .L101 .L100: movq $1, %rax .L104: movq $1, %rbx cmpq $201, %rbx jg .L100 .L101: movq $1, %rdi cmpq $201, %rdi jg .L102
  • 20. for式3 gcc –O2 void f (double * a[], double * b[]) { for (int i = 0; i < 100; i++) for (int j = 0; j < 100; j++) a[i][j] = b[i][j] + i; } .L3: movsd (%rdx,%rax), %xmm0 addsd %xmm1, %xmm0 movsd %xmm0, (%rcx,%rax) addq $8, %rax cmpq $800, %rax jne .L3 addq $1, %r8 cmpq $100, %r8 jne .L2 rep ret xorl %r8d, %r8d .L2: pxor %xmm1, %xmm1 movq (%rdi,%r8,8), %rcx movq (%rsi,%r8,8), %rdx xorl %eax, %eax cvtsi2sd %r8d, %xmm1
  • 21. for式4 共通式 let f a b c = for i = 0 to 100 do a.(i) <- a.(i) +. c.(i); b.(i) <- a.(i) +. c.(i); done .L101: movsd -4(%rax,%rsi,4), %xmm0 addsd -4(%rdi,%rsi,4), %xmm0 movsd %xmm0, -4(%rax,%rsi,4) movsd -4(%rax,%rsi,4), %xmm0 addsd -4(%rdi,%rsi,4), %xmm0 movsd %xmm0, -4(%rbx,%rsi,4) movq %rsi, %rdx addq $2, %rsi cmpq $201, %rdx jne .L101 .L100: movq $1, %rax ret .L102: movq $1, %rsi cmpq $201, %rsi jg .L100
  • 22. for式4 gcc void f (double a[], double b[], double c[]) { for (int i = 0; i < 100; i++) { a[i] = a[i] + c[i]; b[i] = a[i] + c[i]; } } f: xorl %eax, %eax .L2: movsd (%rdi,%rax), %xmm0 addsd (%rdx,%rax), %xmm0 movsd %xmm0, (%rdi,%rax) addsd (%rdx,%rax), %xmm0 movsd %xmm0, (%rsi,%rax) addq $8, %rax cmpq $800, %rax jne .L2 rep ret .L102: movq $1, %rsi cmpq $201, %rsi jg .L100 SIMD化されてる 共通式の除去
  • 23. for式5 共通式2 let f a b n = for i = 0 to 100 do a.(i) <- n +. 3.0; b.(i) <- n +. 4.0; done f: movsd .LC0(%rip), %xmm1 xorl %eax, %eax addsd %xmm0, %xmm1 addsd .LC1(%rip), %xmm0 .L2: movsd %xmm1, (%rdi,%rax) movsd %xmm0, (%rsi,%rax) addq $8, %rax cmpq $800, %rax jne .L2 rep ret
  • 24. 感想 ? 想像したとおりの愚直なアセンブラが出る ? あんまり共通式とか取られない ? gccと比べて出来てない目立つ最適化 – 分岐の除去(!) – 共通式 – ループアンローリング(-O3)
  • 25. match1 let f = function | x :: xs -> [x] | [] -> [0] .L102: subq $24, %r15 movq caml_young_limit @GOTPCREL(%rip), %rax cmpq (%rax), %r15 jb .L103 leaq 8(%r15), %rax movq $2048, -8(%rax) movq (%rbx), %rbx movq %rbx, (%rax) movq $1, 8(%rax) addq $8, %rsp ret subq $8, %rsp .L101: movq %rax, %rbx cmpq $1, %rbx je .L100
  • 26. list1 let f x = x :: x :: x :: [] movq $1, 8(%rax) leaq 24(%rax), %rdi movq $2048, -8(%rdi) movq %rbx, (%rdi) movq %rax, 8(%rdi) addq $48, %rax movq $2048, -8(%rax) movq %rbx, (%rax) movq %rdi, 8(%rax) addq $8, %rsp ret .L102: call caml_call_gc@PLT .L103: jmp .L101 subq $8, %rsp .L100: movq %rax, %rbx .L101: subq $72, %r15 movq caml_young_limit @GOTPCREL(%rip), %rax cmpq (%rax), %r15 jb .L102 leaq 8(%r15), %rax movq $2048, -8(%rax) movq %rbx, (%rax)
  • 27. まとめ? ? 小さい関数のasmなら普通に読める ? OCamlコンパイラは最適化が足りない – まぁGCのオーバーヘッドとか気にした方がいい – 普通はあんまり気にならない ? ループの最内とかは気にしたほうが良い ? 数値を計算するときはfloatのmallocがきびしい インライン展開が有効