Adakah anda fikir kedua-dua pilihan untuk menguji keadaan di dalam gelung adalah setara dalam prestasi?
if a > b && c*2 > d {
....
}
// ΠΈ
if a <= b {
continue;
}
if c*2 > d {
....
}
Semuanya bermula dengan "memanaskan otak"; Saya terpaksa memberikan contoh carian optimum untuk nombor genap terbesar dalam susunan integer [-x....x]. Saya tertanya-tanya sejauh mana prestasi yang lebih baik jika saya menggunakan pendaraban logik dengan 1 untuk mengetahui sama ada nombor itu genap atau tidak.
//Ρ ΡΠ΅ΡΠ½ΡΡ
ΡΠΈΡΠ΅Π» ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠΉ Π±ΠΈΡ Π²ΡΠ΅Π³Π΄Π° ΡΠ°Π²Π΅Π½ 0
value & 1 == 0
//vs ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΌΠ΅ΡΠΎΠ΄
value % 2 == 0
Pengalaman pengaturcaraan saya dalam Go tidak begitu luas, hanya lebih setahun setengah, saya menggunakannya, walaupun kerap, tetapi semata-mata untuk tujuan utilitarian (baik, mungkin kecuali untuk satu projek yang berkaitan dengan perkhidmatan http beban tinggi), jadi saya bermula dengannya. Buka GoLand dan tulis ujian mudah
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)+"ttduration %s", result.Duration)
// Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌ ΡΠ΅ΡΡ "ΠΊΠΎΠ½ΡΡΠ½ΠΊΡΠΈΠΈ"
result = maxEvenConjunction("maxEvenConjunction", arr)
log.Printf(result.Name+"t result: "+fmt.Sprint(result.Value)+"ttduration %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
}
Kami mendapat keputusan yang menunjukkan bahawa semakin tinggi ambang, semakin kerap turun naik dalam prestasi muncul.
Bandingkanmax 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
Adalah jelas bahawa dalam kes ini, untuk ambang yang berbeza kami mempunyai set data ujian yang berbeza, beban pemproses (pada komputer riba i5-2540M saya) berbeza-beza sekitar 20..30%, memori yang diduduki oleh aplikasi yang dijalankan dari GoLand adalah secara purata kira-kira 813MB - ini juga menjejaskan kebolehpercayaan keputusan, anda perlu menyimpan kes ujian pada cakera dan menjalankan semua ujian untuk setiap ambang secara berasingan antara satu sama lain.
Dan sekarang, memikirkan bagaimana untuk melaksanakan semua ini dengan kos yang minimum, saya secara automatik membetulkan pemeriksaan keadaan
if value > current && value&1 == 0 {
current = value
}
pada
if value <= current {
continue;
}
if value&1 == 0 {
current = value
}
Saya menjalankan ujian sekali lagi... dan saya berhenti memahami apa-apa :)
Masa yang dibelanjakan untuk pelaksanaan mula berbeza bukan mengikut peratusan/pecahan peratus, tetapi sebanyak 10..15%. Saya cepat menambah 2 lagi ujian:
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
}
Saya menjalankannya dan mendapatkan gambar ini:kapasiti tatasusunan awal: 100000000
ambang maksimum: 128
maxEvenDividing hasil: 126 tempoh 116.0066ms
hasil maxEvenDividing2: 126 tempoh 79.0045ms
hasil maxEvenConjunction: 126 tempoh 114.0065ms
hasil maxEvenConjunction2: 126 tempoh 83.0048ms
ambang maksimum: 256
maxEvenDividing hasil: 254 tempoh 111.0063ms
hasil maxEvenDividing2: 254 tempoh 77.0044ms
hasil maxEvenConjunction: 254 tempoh 110.0063ms
hasil maxEvenConjunction2: 254 tempoh 80.0046ms
ambang maksimum: 512
maxEvenDividing hasil: 510 tempoh 114.0066ms
hasil maxEvenDividing2: 510 tempoh 80.0045ms
hasil maxEvenConjunction: 510 tempoh 110.0063ms
hasil maxEvenConjunction2: 510 tempoh 80.0046ms
ambang maksimum: 1024
maxEvenDividing hasil: 1022 tempoh 109.0063ms
hasil maxEvenDividing2: 1022 tempoh 77.0044ms
hasil maxEvenConjunction: 1022 tempoh 111.0063ms
hasil maxEvenConjunction2: 1022 tempoh 81.0047ms
ambang maksimum: 2048
maxEvenDividing hasil: 2046 tempoh 114.0065ms
hasil maxEvenDividing2: 2046 tempoh 79.0045ms
hasil maxEvenConjunction: 2046 tempoh 113.0065ms
hasil maxEvenConjunction2: 2046 tempoh 81.0046ms
ambang maksimum: 4096
maxEvenDividing hasil: 4094 tempoh 114.0065ms
hasil maxEvenDividing2: 4094 tempoh 80.0046ms
hasil maxEvenConjunction: 4094 tempoh 111.0063ms
hasil maxEvenConjunction2: 4094 tempoh 78.0045ms
ambang maksimum: 8192
maxEvenDividing hasil: 8190 tempoh 107.0062ms
hasil maxEvenDividing2: 8190 tempoh 77.0044ms
hasil maxEvenConjunction: 8190 tempoh 111.0063ms
hasil maxEvenConjunction2: 8190 tempoh 77.0044ms
ambang maksimum: 16384
maxEvenDividing hasil: 16382 tempoh 109.0063ms
hasil maxEvenDividing2: 16382 tempoh 77.0044ms
hasil maxEvenConjunction: 16382 tempoh 108.0062ms
hasil maxEvenConjunction2: 16382 tempoh 77.0044ms
ambang maksimum: 32768
maxEvenDividing hasil: 32766 tempoh 112.0064ms
hasil maxEvenDividing2: 32766 tempoh 77.0044ms
hasil maxEvenConjunction: 32766 tempoh 109.0062ms
hasil maxEvenConjunction2: 32766 tempoh 78.0045ms
ambang maksimum: 65536
maxEvenDividing hasil: 65534 tempoh 109.0062ms
hasil maxEvenDividing2: 65534 tempoh 75.0043ms
hasil maxEvenConjunction: 65534 tempoh 109.0063ms
hasil maxEvenConjunction2: 65534 tempoh 79.0045ms
ambang maksimum: 131072
maxEvenDividing hasil: 131070 tempoh 108.0061ms
hasil maxEvenDividing2: 131070 tempoh 76.0044ms
hasil maxEvenConjunction: 131070 tempoh 110.0063ms
hasil maxEvenConjunction2: 131070 tempoh 80.0046ms
ambang maksimum: 262144
maxEvenDividing hasil: 262142 tempoh 110.0063ms
hasil maxEvenDividing2: 262142 tempoh 76.0044ms
hasil maxEvenConjunction: 262142 tempoh 107.0061ms
hasil maxEvenConjunction2: 262142 tempoh 78.0044ms
ambang maksimum: 524288
maxEvenDividing hasil: 524286 tempoh 109.0062ms
hasil maxEvenDividing2: 524286 tempoh 78.0045ms
hasil maxEvenConjunction: 524286 tempoh 109.0062ms
hasil maxEvenConjunction2: 524286 tempoh 80.0046ms
ambang maksimum: 1048576
maxEvenDividing hasil: 1048574 tempoh 109.0063ms
hasil maxEvenDividing2: 1048574 tempoh 80.0045ms
hasil maxEvenConjunction: 1048574 tempoh 114.0066ms
hasil maxEvenConjunction2: 1048574 tempoh 78.0044ms
ambang maksimum: 2097152
maxEvenDividing hasil: 2097150 tempoh 111.0064ms
hasil maxEvenDividing2: 2097150 tempoh 79.0045ms
hasil maxEvenConjunction: 2097150 tempoh 112.0064ms
hasil maxEvenConjunction2: 2097150 tempoh 77.0044ms
ambang maksimum: 4194304
maxEvenDividing hasil: 4194302 tempoh 111.0063ms
hasil maxEvenDividing2: 4194302 tempoh 78.0045ms
hasil maxEvenConjunction: 4194302 tempoh 111.0063ms
hasil maxEvenConjunction2: 4194302 tempoh 77.0044ms
ambang maksimum: 8388608
maxEvenDividing hasil: 8388606 tempoh 109.0062ms
hasil maxEvenDividing2: 8388606 tempoh 78.0045ms
hasil maxEvenConjunction: 8388606 tempoh 114.0065ms
hasil maxEvenConjunction2: 8388606 tempoh 78.0045ms
ambang maksimum: 16777216
maxEvenDividing hasil: 16777214 tempoh 109.0062ms
hasil maxEvenDividing2: 16777214 tempoh 77.0044ms
hasil maxEvenConjunction: 16777214 tempoh 109.0063ms
hasil maxEvenConjunction2: 16777214 tempoh 77.0044ms
ambang maksimum: 33554432
maxEvenDividing hasil: 33554430 tempoh 113.0065ms
hasil maxEvenDividing2: 33554430 tempoh 78.0045ms
hasil maxEvenConjunction: 33554430 tempoh 110.0063ms
hasil maxEvenConjunction2: 33554430 tempoh 80.0045ms
ambang maksimum: 67108864
maxEvenDividing hasil: 67108860 tempoh 112.0064ms
hasil maxEvenDividing2: 67108860 tempoh 77.0044ms
hasil maxEvenConjunction: 67108860 tempoh 112.0064ms
hasil maxEvenConjunction2: 67108860 tempoh 80.0046ms
ambang maksimum: 134217728
maxEvenDividing hasil: 134217726 tempoh 109.0063ms
hasil maxEvenDividing2: 134217726 tempoh 78.0044ms
hasil maxEvenConjunction: 134217726 tempoh 114.0065ms
hasil maxEvenConjunction2: 134217726 tempoh 81.0047ms
ambang maksimum: 268435456
maxEvenDividing hasil: 268435446 tempoh 111.0064ms
hasil maxEvenDividing2: 268435446 tempoh 79.0045ms
hasil maxEvenConjunction: 268435446 tempoh 114.0065ms
hasil maxEvenConjunction2: 268435446 tempoh 79.0045ms
ambang maksimum: 536870912
maxEvenDividing hasil: 536870910 tempoh 107.0062ms
hasil maxEvenDividing2: 536870910 tempoh 76.0043ms
hasil maxEvenConjunction: 536870910 tempoh 109.0062ms
hasil maxEvenConjunction2: 536870910 tempoh 80.0046ms
Saya tidak dapat mencari penjelasan yang jelas mengapa pengkompil Go tidak mengoptimumkan kod dan sentiasa menyemak syarat kedua, walaupun yang pertama adalah palsu. Atau mungkin mata saya hanya kabur dan saya tidak nampak sebarang kesilapan yang jelas? Atau adakah anda perlu memberikan beberapa arahan khas kepada pengkompil? Saya akan gembira untuk komen yang masuk akal.
PS: Ya, hanya untuk keseronokan, saya menjalankan ujian serupa pada Java 5 dan Java 7/8 - semuanya jelas, masa pelaksanaan adalah sama.
Sumber: www.habr.com