KDOC 69: 『Go compiler intrinsics』
この文書のステータス
- 作成
- 2024-02-04 貴島
- レビュー
- 2024-02-06 貴島
概要
Go compiler intrinsics | Dave Cheneyを読んだメモ。
コンパイラには、intrinsic(組み込み関数)という機能がある。組み込みで用意された関数によって高速に処理できる。アセンブラのレベルでCPUに最適化されたアルゴリズムを用いることで、高速化できる。Goではアセンブラで関数の本体を書くのをサポートしている。しかし、アセンブラを直に書くのは大変なので、コンパイラが組み込み関数として用意してくれている。
メモ
- assembly languageで書いてもインライン展開されないので遅い。アセンブラで書く代わりに、組み込み関数が用意されている
- 組み込み関数はGoで書かれている
- 特定分野に重要な演算はCPUネイティブな命令がサポートされている。それを使うことで高速になる
- 暗号とか圧縮分野
https://github.com/kd-collective/go/blob/2eca0b1e1663d826893b6b1fd8bd89da98e65d1e/src/math/bits/bits.go#L116-L122
// OnesCount returns the number of one bits (“population count”) in x. func OnesCount(x uint) int { if UintSize == 32 { return OnesCount32(uint32(x)) } return OnesCount64(uint64(x)) }
- OnesCount組み込み関数を使ったとき発行されるアセンブラを見ると、POPCNT命令があるのを確認できる。これがCPUネイティブの命令である
- CMPB命令で、CPUがPOPCNT命令をネイティブサポートしているか事前チェックしている
https://github.com/kd-collective/go/blob/2eca0b1e1663d826893b6b1fd8bd89da98e65d1e/src/sync/atomic/type.go#L87-L88
// Add atomically adds delta to x and returns the new value. func (x *Int32) Add(delta int32) (new int32) { return AddInt32(&x.v, delta) }
- CPUのアトミックインクリメントは、競合を回避するために設計された操作。同じ変数を同時にインクリメントしようとしても正確にインクリメントできる。CPUの命令セットで用意されているため安全かつコストを少なく操作できる
- アトミックカウンタのコードを書くとLOCK命令が発行されることを確認できる
- コンパイラはCPUネイティブの命令がサポートされてないときは、フォールバックしてピュアGoコードの操作を使う
関連
- KDOC 45: プログラミング言語の内部的な違いをアセンブリから調べる。発行する命令を確認する方法は正しそう