if a > b && c*2 > d { .... } // if a <= b { continue; } if c*2 > d { .... }
すべては「脳の準備」から始まり、最大偶数の整数の配列[-x .... x]による最適な検索の例を示す必要がありました。 偶数を見つけるために、1による論理乗算を使用すると、パフォーマンスがどれほど向上するのか疑問に思いました。
// 0 value & 1 == 0 //vs value % 2 == 0
Goでの私のプログラミングエクスペリエンスはそれほど大きくなく、1年半半ほどでしたが、頻繁に使用しましたが、純粋に実用的な目的で使用しました(多分、負荷の高いhttpサービスに関連する1つのプロジェクトを除く)。 GoLandを開き、簡単なテストを作成します
package main import ( "fmt" "log" "math" "math/rand" "time" ) const size = 100000000 //math.MaxInt32*2 type Result struct { Name string Duration time.Duration Value int32 } func main() { log.Println("initial array capacity: " + fmt.Sprint(size)) var maxValue int32 // // . , // // , for maxValue = 128; maxValue < math.MaxInt32/2+1; maxValue = maxValue * 2 { test(maxValue) } } func test(maxValue int32) { log.Println("max threshold: " + fmt.Sprint(maxValue)) arr := make([]int32, size) for i := range arr { arr[i] = rand.Int31n(maxValue) // sign := rand.Intn(2) if sign == 1 { arr[i] = -arr[i] } } // " " result := maxEvenDividing("maxEvenDividing", arr) log.Printf(result.Name+"\t result: "+fmt.Sprint(result.Value)+"\t\tduration %s", result.Duration) // "" result = maxEvenConjunction("maxEvenConjunction", arr) log.Printf(result.Name+"\t result: "+fmt.Sprint(result.Value)+"\t\tduration %s", result.Duration) } func maxEvenDividing(name string, arr []int32) Result { start := time.Now() var current int32 = math.MinInt32 for _, value := range arr { if value > current && value%2 == 0 { current = value } } duration := time.Since(start) result := Result{name, duration, current} return result } func maxEvenConjunction(name string, arr []int32) Result { start := time.Now() var current int32 = math.MinInt32 for _, value := range arr { if value > current && value&1 == 0 { current = value } } duration := time.Since(start) result := Result{name, duration, current} return result }
しきい値が高いほど、パフォーマンスに関して変動が頻繁に現れるという結果が得られます。
比較する
max threshold: 128
maxEvenDividing result: 126 duration 116.0067ms
maxEvenConjunction result: 126 duration 116.0066ms
max threshold: 16384
maxEvenDividing result: 16382 duration 115.0066ms
maxEvenConjunction result: 16382 duration 111.0064ms
......
max threshold: 8388608
maxEvenDividing result: 8388606 duration 109.0063ms
maxEvenConjunction result: 8388606 duration 109.0062ms
max threshold: 16777216
maxEvenDividing result: 16777214 duration 108.0062ms
maxEvenConjunction result: 16777214 duration 109.0062ms
max threshold: 33554432
maxEvenDividing result: 33554430 duration 114.0066ms
maxEvenConjunction result: 33554430 duration 110.0063ms
max threshold: 67108864
maxEvenDividing result: 67108860 duration 111.0064ms
maxEvenConjunction result: 67108860 duration 109.0062ms
max threshold: 134217728
maxEvenDividing result: 134217726 duration 108.0062ms
maxEvenConjunction result: 134217726 duration 109.0063ms
max threshold: 268435456
maxEvenDividing result: 268435446 duration 111.0063ms
maxEvenConjunction result: 268435446 duration 110.0063ms
この場合、異なるしきい値に対して異なるテストデータセットがあり、プロセッサー負荷(i5-2540Mラップトップで)が20..30%前後で変化し、GoLandの下から実行されるアプリケーションが占有するメモリーが平均で約813 MBであることは明らかです-これも結果の信頼性に影響するため、テストスイートの保存をディスクに実装し、各しきい値のすべてのテストを相互に分離して実行する必要があります。
最小限の費用でこれらすべてを実装する方法を考えて、条件チェックを自動的に修正します
if value > current && value&1 == 0 { current = value }
に
if value <= current { continue; } if value&1 == 0 { current = value }
私は再びテストを実行します...そして何かを理解することをやめます
実行に費やされる時間は、既にパーセント/パーセントの割合ではなく、10..15%ずつ異なりますが、さらに2つのテストを追加します。
func maxEvenDividing2(name string, arr []int32) Result { start := time.Now() var current int32 = math.MinInt32 for _, value := range arr { if value <= current { continue } if value%2 == 0 { current = value } } duration := time.Since(start) result := Result{name, duration, current} return result } func maxEvenConjunction2(name string, arr []int32) Result { start := time.Now() var current int32 = math.MinInt32 for _, value := range arr { if value <= current { continue } if value&1 == 0 { current = value } } duration := time.Since(start) result := Result{name, duration, current} return result }
私はこの写真を起動して取得します:
初期アレイ容量:100000000
最大しきい値:128
maxEvenDividing結果:126持続時間116.0066ms
maxEvenDividing2結果:126期間79.0045ms
maxEvenConjunctionの結果:126持続時間114.0065ms
maxEvenConjunction2の結果:126期間83.0048ms
最大しきい値:256
maxEvenDividing結果:254期間111.0063ms
maxEvenDividing2結果:254持続時間77.0044ms
maxEvenConjunctionの結果:254期間110.0063ms
maxEvenConjunction2の結果:254期間80.0046ms
最大しきい値:512
maxEvenDividingの結果:510期間114.0066ms
maxEvenDividing2の結果:510期間80.0045ms
maxEvenConjunctionの結果:510期間110.0063ms
maxEvenConjunction2の結果:510期間80.0046ms
最大しきい値:1024
maxEvenDividing結果:1022持続時間109.0063ms
maxEvenDividing2結果:1022期間77.0044ms
maxEvenConjunctionの結果:1022期間111.0063ms
maxEvenConjunction2結果:1022期間81.0047ms
最大しきい値:2048
maxEvenDividing結果:2046期間114.0065ms
maxEvenDividing2結果:2046期間79.0045ms
maxEvenConjunctionの結果:2046期間113.0065ms
maxEvenConjunction2の結果:2046期間81.0046ms
最大しきい値:4096
maxEvenDividing結果:4094期間114.0065ms
maxEvenDividing2結果:4094期間80.0046ms
maxEvenConjunctionの結果:4094期間111.0063ms
maxEvenConjunction2の結果:4094期間78.0045ms
最大しきい値:8192
maxEvenDividingの結果:8190期間107.0062ms
maxEvenDividing2結果:8190期間77.0044ms
maxEvenConjunctionの結果:8190期間111.0063ms
maxEvenConjunction2の結果:8190期間77.0044ms
最大しきい値:16384
maxEvenDividing結果:16382期間109.0063ms
maxEvenDividing2結果:16382期間77.0044ms
maxEvenConjunctionの結果:16382期間108.0062ms
maxEvenConjunction2の結果:16382期間77.0044ms
最大しきい値:32768
maxEvenDividingの結果:32766の持続時間112.0064ms
maxEvenDividing2結果:32766期間77.0044ms
maxEvenConjunctionの結果:32766の持続時間109.0062ms
maxEvenConjunction2の結果:32766の持続時間78.0045ms
最大しきい値:65536
maxEvenDividingの結果:65534期間109.0062ms
maxEvenDividing2結果:65534期間75.0043ms
maxEvenConjunctionの結果:65534期間109.0063ms
maxEvenConjunction2の結果:65534期間79.0045ms
最大しきい値:131072
maxEvenDividingの結果:131070期間108.0061ms
maxEvenDividing2の結果:131070期間76.0044ms
maxEvenConjunctionの結果:131070期間110.0063ms
maxEvenConjunction2の結果:131070期間80.0046ms
最大しきい値:262144
maxEvenDividing結果:262142期間110.0063ms
maxEvenDividing2結果:262142期間76.0044ms
maxEvenConjunctionの結果:262142期間107.0061ms
maxEvenConjunction2の結果:262142の継続時間78.0044ms
最大しきい値:524288
maxEvenDividingの結果:524286期間109.0062ms
maxEvenDividing2の結果:524286期間78.0045ms
maxEvenConjunctionの結果:524286期間109.0062ms
maxEvenConjunction2の結果:524286期間80.0046ms
最大しきい値:1048576
maxEvenDividingの結果:1048574期間109.0063ms
maxEvenDividing2の結果:1048574期間80.0045ms
maxEvenConjunctionの結果:1048574期間114.0066ms
maxEvenConjunction2の結果:1048574期間78.0044ms
最大しきい値:2097152
maxEvenDividing結果:2097150期間111.0064ms
maxEvenDividing2結果:2097150期間79.0045ms
maxEvenConjunctionの結果:2097150期間112.0064ms
maxEvenConjunction2の結果:2097150期間77.0044ms
最大しきい値:4194304
maxEvenDividing結果:4194302期間111.0063ms
maxEvenDividing2の結果:4194302期間78.0045ms
maxEvenConjunctionの結果:4194302期間111.0063ms
maxEvenConjunction2の結果:4194302期間77.0044ms
最大しきい値:8388608
maxEvenDividingの結果:8388606期間109.0062ms
maxEvenDividing2の結果:8388606期間78.0045ms
maxEvenConjunctionの結果:8388606期間114.0065ms
maxEvenConjunction2の結果:8388606の継続時間78.0045ms
最大しきい値:16777216
maxEvenDividingの結果:16777214期間109.0062ms
maxEvenDividing2結果:16777214期間77.0044ms
maxEvenConjunctionの結果:16777214期間109.0063ms
maxEvenConjunction2の結果:16777214期間77.0044ms
最大しきい値:33554432
maxEvenDividing結果:33554430継続時間113.0065ms
maxEvenDividing2結果:33554430継続時間78.0045ms
maxEvenConjunctionの結果:33554430期間110.0063ms
maxEvenConjunction2の結果:33554430期間80.0045ms
最大しきい値:67108864
maxEvenDividing結果:67108860期間112.0064ms
maxEvenDividing2結果:67108860期間77.0044ms
maxEvenConjunctionの結果:67108860期間112.0064ms
maxEvenConjunction2の結果:67108860の継続時間80.0046ms
最大しきい値:134217728
maxEvenDividingの結果:134217726期間109.0063ms
maxEvenDividing2の結果:134217726期間78.0044ms
maxEvenConjunctionの結果:134217726期間114.0065ms
maxEvenConjunction2の結果:134217726期間81.0047ms
最大しきい値:268435456
maxEvenDividingの結果:268435446期間111.0064ms
maxEvenDividing2の結果:268435446継続時間79.0045ms
maxEvenConjunctionの結果:268435446期間114.0065ms
maxEvenConjunction2の結果:268435446継続時間79.0045ms
最大しきい値:536870912
maxEvenDividingの結果:536870910期間107.0062ms
maxEvenDividing2結果:536870910期間76.0043ms
maxEvenConjunctionの結果:536870910期間109.0062ms
maxEvenConjunction2の結果:536870910期間80.0046ms
最大しきい値:128
maxEvenDividing結果:126持続時間116.0066ms
maxEvenDividing2結果:126期間79.0045ms
maxEvenConjunctionの結果:126持続時間114.0065ms
maxEvenConjunction2の結果:126期間83.0048ms
最大しきい値:256
maxEvenDividing結果:254期間111.0063ms
maxEvenDividing2結果:254持続時間77.0044ms
maxEvenConjunctionの結果:254期間110.0063ms
maxEvenConjunction2の結果:254期間80.0046ms
最大しきい値:512
maxEvenDividingの結果:510期間114.0066ms
maxEvenDividing2の結果:510期間80.0045ms
maxEvenConjunctionの結果:510期間110.0063ms
maxEvenConjunction2の結果:510期間80.0046ms
最大しきい値:1024
maxEvenDividing結果:1022持続時間109.0063ms
maxEvenDividing2結果:1022期間77.0044ms
maxEvenConjunctionの結果:1022期間111.0063ms
maxEvenConjunction2結果:1022期間81.0047ms
最大しきい値:2048
maxEvenDividing結果:2046期間114.0065ms
maxEvenDividing2結果:2046期間79.0045ms
maxEvenConjunctionの結果:2046期間113.0065ms
maxEvenConjunction2の結果:2046期間81.0046ms
最大しきい値:4096
maxEvenDividing結果:4094期間114.0065ms
maxEvenDividing2結果:4094期間80.0046ms
maxEvenConjunctionの結果:4094期間111.0063ms
maxEvenConjunction2の結果:4094期間78.0045ms
最大しきい値:8192
maxEvenDividingの結果:8190期間107.0062ms
maxEvenDividing2結果:8190期間77.0044ms
maxEvenConjunctionの結果:8190期間111.0063ms
maxEvenConjunction2の結果:8190期間77.0044ms
最大しきい値:16384
maxEvenDividing結果:16382期間109.0063ms
maxEvenDividing2結果:16382期間77.0044ms
maxEvenConjunctionの結果:16382期間108.0062ms
maxEvenConjunction2の結果:16382期間77.0044ms
最大しきい値:32768
maxEvenDividingの結果:32766の持続時間112.0064ms
maxEvenDividing2結果:32766期間77.0044ms
maxEvenConjunctionの結果:32766の持続時間109.0062ms
maxEvenConjunction2の結果:32766の持続時間78.0045ms
最大しきい値:65536
maxEvenDividingの結果:65534期間109.0062ms
maxEvenDividing2結果:65534期間75.0043ms
maxEvenConjunctionの結果:65534期間109.0063ms
maxEvenConjunction2の結果:65534期間79.0045ms
最大しきい値:131072
maxEvenDividingの結果:131070期間108.0061ms
maxEvenDividing2の結果:131070期間76.0044ms
maxEvenConjunctionの結果:131070期間110.0063ms
maxEvenConjunction2の結果:131070期間80.0046ms
最大しきい値:262144
maxEvenDividing結果:262142期間110.0063ms
maxEvenDividing2結果:262142期間76.0044ms
maxEvenConjunctionの結果:262142期間107.0061ms
maxEvenConjunction2の結果:262142の継続時間78.0044ms
最大しきい値:524288
maxEvenDividingの結果:524286期間109.0062ms
maxEvenDividing2の結果:524286期間78.0045ms
maxEvenConjunctionの結果:524286期間109.0062ms
maxEvenConjunction2の結果:524286期間80.0046ms
最大しきい値:1048576
maxEvenDividingの結果:1048574期間109.0063ms
maxEvenDividing2の結果:1048574期間80.0045ms
maxEvenConjunctionの結果:1048574期間114.0066ms
maxEvenConjunction2の結果:1048574期間78.0044ms
最大しきい値:2097152
maxEvenDividing結果:2097150期間111.0064ms
maxEvenDividing2結果:2097150期間79.0045ms
maxEvenConjunctionの結果:2097150期間112.0064ms
maxEvenConjunction2の結果:2097150期間77.0044ms
最大しきい値:4194304
maxEvenDividing結果:4194302期間111.0063ms
maxEvenDividing2の結果:4194302期間78.0045ms
maxEvenConjunctionの結果:4194302期間111.0063ms
maxEvenConjunction2の結果:4194302期間77.0044ms
最大しきい値:8388608
maxEvenDividingの結果:8388606期間109.0062ms
maxEvenDividing2の結果:8388606期間78.0045ms
maxEvenConjunctionの結果:8388606期間114.0065ms
maxEvenConjunction2の結果:8388606の継続時間78.0045ms
最大しきい値:16777216
maxEvenDividingの結果:16777214期間109.0062ms
maxEvenDividing2結果:16777214期間77.0044ms
maxEvenConjunctionの結果:16777214期間109.0063ms
maxEvenConjunction2の結果:16777214期間77.0044ms
最大しきい値:33554432
maxEvenDividing結果:33554430継続時間113.0065ms
maxEvenDividing2結果:33554430継続時間78.0045ms
maxEvenConjunctionの結果:33554430期間110.0063ms
maxEvenConjunction2の結果:33554430期間80.0045ms
最大しきい値:67108864
maxEvenDividing結果:67108860期間112.0064ms
maxEvenDividing2結果:67108860期間77.0044ms
maxEvenConjunctionの結果:67108860期間112.0064ms
maxEvenConjunction2の結果:67108860の継続時間80.0046ms
最大しきい値:134217728
maxEvenDividingの結果:134217726期間109.0063ms
maxEvenDividing2の結果:134217726期間78.0044ms
maxEvenConjunctionの結果:134217726期間114.0065ms
maxEvenConjunction2の結果:134217726期間81.0047ms
最大しきい値:268435456
maxEvenDividingの結果:268435446期間111.0064ms
maxEvenDividing2の結果:268435446継続時間79.0045ms
maxEvenConjunctionの結果:268435446期間114.0065ms
maxEvenConjunction2の結果:268435446継続時間79.0045ms
最大しきい値:536870912
maxEvenDividingの結果:536870910期間107.0062ms
maxEvenDividing2結果:536870910期間76.0043ms
maxEvenConjunctionの結果:536870910期間109.0062ms
maxEvenConjunction2の結果:536870910期間80.0046ms
Goコンパイラがコードを最適化せず、2番目の条件を常にチェックする理由の明確な説明。たとえ最初の条件がfalseであっても、私は見つけませんでした。 それとも私の目が「ぼやけ」て、明らかな間違いが見られないのでしょうか? または、コンパイラに特別な指示を指定する必要がありますか? 私は賢明なコメントに満足しています。
PS:はい、楽しみのために、Java 5とJava 7/8で同様のテストを実行しました。すべてが明確で、実行時間は同じです。