Go 1.22のrange over int

今月リリースされたGo 1.22でrange over intと言う拡張と言うか表記表現が加わった。

 

よく使われるforループは以前以下のような書き方をしていた。

    for i := 0; i < N; i++ {
    // ループの中
    }

iがループ変数で0からN-1までN回のループとなる。

Pythonなどでは既にある記法であるが以下のような表現が可能になった。

    for i := range N {
    // ループの中
    }

ベンチマークなどのループ変数のiを参照しないケースであれば,さらに以下のように省略も可能である。

  for range N {
    // ループの中
    }

 

ということで少し試してみた。

以前から制作している将棋エンジンの対応可能なループを全てrange over intに書き換えてみたところ,ベンチマーク上は特に変化が無かった。

整数の固定ループ化で速度向上を期待していたところ微妙なところむしろ遅くなった印象である。

 

心当たりはループ変数の扱いの変化である。

Go 1.22ではforループ時のループ変数を別アドレスに取るように変更になった。聞きかじったレベルの理由としては,Goでよく実装されるループ中のgoroutineでループ変数を参照する場合参照時には次のループに入っているケースが多く,よくある対応としてループ内変数に一時保存して参照しなくてはならない。この対応を不要にするためにアドレスを個々に与えているようである。

しかしながら,これをやってしまうとN回ループにN個の整数を別アドレスに確保する,つまりリスト生成をしてしまうことになる。せっかくの高速化チャンスである固定ループが台無しになっていると思われる。

 

まぁ,Goの使われ方を考える限り間違った対応でもないしこのレベルの速度を気にするのはHPC分野の人くらいだろう。Goでコーデックの類も書かれているらしいが気にならないのだろうか。