Go language part 5

■ このスレッドは過去ログ倉庫に格納されています
2022/02/27(日) 07:43:20.04ID:uWHjNeVw
Goについて扱うスレッドです。
GoはGoogleによって開発された言語です。

公式
https://golang.org

公式ドキュメント
https://golang.org/doc/

公式外パッケージドキュメント
https://godoc.org

ブラウザ上で試し書き
https://play.golang.org


※前スレ
Go language part 4
https://mevius.5ch.net/test/read.cgi/tech/1605467680/
2022/02/27(日) 07:45:13.76ID:uWHjNeVw
公式
https://golang.org

公式ドキュメント
https://golang.org/doc/

公式外パッケージドキュメント
https://godoc.org

ブラウザ上で試し書き
https://play.golang.org
2022/02/27(日) 07:46:00.05ID:uWHjNeVw
あ、これ2のテンプレじゃないのか
2022/02/27(日) 08:59:11.36ID:PVy06kKY
>>992(前スレ)
読んだ。で、やっぱり奇妙なんだけど、多分オーバーヘッドはないと思うよ。

一般的にはガードページなんて必要なくて、コピーオンライトと同じで、
ページ境界を跨いだ場合はハードウェアで検出出来るから、まず普通はそれを使う。
この場合は自前でのチェックは必要ない(ソフトウェアには必要ない)ので、オーバーヘッドはない。
だからGoの当初の初期スタックサイズが4kだったのは非常に納得出来た。ここまではいい。

これを小さくするならハードウェアのサポート無しになるから当然自前でチェックするしかないが、この場合、
・2kも大きすぎ。自分でやるならRustのように64Bytesからとか、4kに拘らず凄く小さいスタックサイズから可能だし、普通はそうする。
・そもそも必要スタックサイズを予見出来ない。というか出来るならコンパイル時に確定的に割り当てれば済んでる。
であって、Rustの実装は非常に納得出来るのだけど、Goのは若干意味不明なんだよ。
(ただまあ何かしら理由はあると思うけど)

2kとかいう、4kに拘ったサイズになってるんだから、多分何かしらハードウェアのサポートを受けてて、
自前ではスタックサイズのチェックはしてないと思うよ。(つまりオーバーヘッドがない)
可能性があるのは、2kをはみ出る時には4k境界を跨ぐようにして(つまりまずは上側を割り当てる)
はみ出た時に2kずらしていくとかだけど。
ただこの方式の場合、初期アロケーションだけは4kでされてしまうので、957のベンチでは40MB越えないとおかしくて、矛盾してる。
だから正直よく分からないが、
多分オーバーヘッドのない方式で実装してて、だから2kとかいう中途半端な巨大サイズになってるのではないかと思う。
2022/02/27(日) 09:14:34.62ID:PVy06kKY
>>998(前スレ)
分かりやすい説明ありがとう。発想は面白いね。
確かにその方式だと死蔵メモリは最小限に留められ、Goの問題は解決されてるはずだね。

>>986(前スレ)
998の通りだと、外部からのプリエンプションではなく、
コルーチンが処理を(自発的に)返してくるから、その単位での切換だろう。
まあこれでも現実的には問題ない気はする。
2022/02/27(日) 09:39:32.40ID:+yReYAPt
ちなみに前スレ1000と同じく、1桁少ない1000スレッドで同じPCでgoを測ると
$ go version
go version go1.13.8 linux/amd64
$ go build main.go && ./t ./main
real 12.02s
user 0.91s
sys 0.22s
rss 3808k
$
やはり4Mを超えない(rssでいいの?とは思うけど)
2022/02/27(日) 10:24:28.50ID:c+lx/lLr
推奨NGWord
正規表現で「.{50}」を設定
長文を排除できます
2022/02/27(日) 14:25:03.95ID:PVy06kKY
>>992(前スレ)
訂正。他も色々漁って、やっぱりオーバーヘッドはあると思えてきた。
ただし多分0〜4cycle/関数呼び出し程度だね。

主に読んだのは以下とか。
https://github.com/tinygo-org/tinygo/issues/2000
https://dave.cheney.net/2014/06/07/five-things-that-make-go-fast
https://dave.cheney.net/2013/06/02/why-is-a-goroutines-stack-infinite

・当初は8kだったが、もっとでかくしろという要求が多かった
・1kに出来てる実装もあるが、こける事もあるから2kがデフォになってる
・同じ図が説明に使われてて、どうやら最初からこの方針らしい

本人達が「チェックしてる」って言うんだからやっぱりそうなんだろう。
一番ありそうな実装は、呼ばれた関数側で最初にチェックする方法で、
つまりローカル変数をスタックに確保するためにスタックポインタからサイズを引く時にチェックする。
これだと、 mov, (sub,) xor, and, jne の追加4命令で(subはチェック無しでも必要)
主にINTパイプで最悪で4cycle、大体の場合はこのあとのLSパイプ(スタック上へのレジスタ待避)に隠れて見えなくなるのではないかと。
だから関数呼び出し毎に0〜4cycのペナルティになる。
ただし、速くなる事はないし、隠れると言っても演算リソースは消費するので、
ハイパースレッディングの場合に相手側のCPUの速度が落ちるのは否めないが。

2k以下にもやれば出来るのだろうけど、やる気がないだけだね。
だから2kで問題なら、コンパイラをいじれば何とかなるのだろうけど、
そこまでやるくらいならRustの方が断然いいね。(後発だから当たり前だけど)
2022/02/27(日) 15:40:03.99ID:F0hGMDSU
関数呼び出しのオーバーヘッドだけど、高階関数らしい高階関数も無いしそういうややこしいことはジェネレーター使う文化だと思ってるな。Genericsが本流になってきたらどうする気だろうもも思ってる。
なお、比較する関数程度の関数はインライン化される。
https://github.com/golang/go/wiki/CompilerOptimizations
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況