いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Goメモ-299 (Intel CPUで int を使って 剰余演算 をすると速度が遅くなる??)(reddit)

概要

以下、自分用のメモです。忘れないうちにメモメモ。。。

Redditで以下のようなスレッドを見つけました。

www.reddit.com

IntelのCPUだと、% を使った計算がとても遅くなるとの話。

内容を見ると、int と uint32 (int32) では、速度が全然異なる状態であると判明している。

どうも、intの状態だと実行時にint64で解釈されてしまうため、遅くなるとのこと。

以下に、AMD (Gitpod) とIntel (自分のマシン) で試してみた結果を記載します。

試してみる

測定対象コードは以下。上のRedditのサイトに載ってたやつとほぼ同じです。

// REFERENCE: https://www.reddit.com/r/golang/comments/11spdom/go_is_23_times_slower_than_js_in_a_similar_code/
package main

import "testing"

func BenchmarkModOperatorInt(b *testing.B) {
    for i := 0; i < b.N; i++ {
        getPrimesInt(20_000)
    }
}

func BenchmarkModOperatorUInt32(b *testing.B) {
    for i := 0; i < b.N; i++ {
        getPrimesUInt32(20_000)
    }
}

func getPrimesInt(limit int) []int {
    primes := []int{}
    for x := 2; x < limit; x++ {
        is_prime := true
        for y := 2; y < x; y++ {
            if x%y == 0 {
                is_prime = false
                break
            }
        }
        if is_prime {
            primes = append(primes, x)
        }
    }
    return primes
}

func getPrimesUInt32(limit uint32) []uint32 {
    primes := []uint32{}
    for x := uint32(2); x < limit; x++ {
        is_prime := true
        for y := uint32(2); y < x; y++ {
            if x%y == 0 {
                is_prime = false
                break
            }
        }
        if is_prime {
            primes = append(primes, x)
        }
    }
    return primes
}

まずは、AMDの方でベンチマーク。

CPU: AMD EPYC 7B13

$ task -d examples/singleapp/mod_operator_performance/
task: [run] go test . -bench . -benchtime 10s -cpu 8
goos: linux
goarch: amd64
pkg: github.com/devlights/try-golang/examples/singleapp/mod_operator_performance
cpu: AMD EPYC 7B13
BenchmarkModOperatorInt-8            261          45508221 ns/op
BenchmarkModOperatorUInt32-8         306          39010884 ns/op
PASS
ok      github.com/devlights/try-golang/examples/singleapp/mod_operator_performance     32.406s

次にIntelの方でベンチマーク。

CPU: Intel(R) Core(TM) i7-10510U

Windows
$ task -d .\examples\singleapp\mod_operator_performance\
task: [run] go test . -bench . -benchtime 10s -cpu 8
goos: windows
goarch: amd64
pkg: github.com/devlights/try-golang/examples/singleapp/mod_operator_performance
cpu: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
BenchmarkModOperatorInt-8             76         147983075 ns/op
BenchmarkModOperatorUInt32-8         274          44632203 ns/op
PASS
ok      github.com/devlights/try-golang/examples/singleapp/mod_operator_performance     28.765s
WSL
$ task -d examples/singleapp/mod_operator_performance/
task: [run] go test . -bench . -benchtime 10s -cpu 8
goos: linux
goarch: amd64
pkg: github.com/devlights/try-golang/examples/singleapp/mod_operator_performance
cpu: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
BenchmarkModOperatorInt-8             78         144214159 ns/op
BenchmarkModOperatorUInt32-8         283          42288278 ns/op
PASS
ok      github.com/devlights/try-golang/examples/singleapp/mod_operator_performance     27.647s

たしかに、Intelの場合、差がとても大きい。

参考情報

github.com

Goのおすすめ書籍

Go言語による並行処理

Go言語による並行処理

Amazon


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。