Pergi kondisi dan keanehan mereka

Apakah menurut Anda kedua opsi ini untuk memeriksa kondisi di dalam satu loop memiliki kinerja yang setara?

if a > b && c*2 > d { .... } //  if a <= b { continue; } if c*2 > d { .... } 

Semuanya dimulai dengan "pemanasan untuk otak", perlu untuk memberikan contoh pencarian optimal untuk array bilangan bulat [-x .... x] dari bilangan genap terbesar. Saya bertanya-tanya berapa banyak kinerja yang lebih tinggi jika, untuk mengetahui angka genap atau tidak, gunakan perkalian logis dengan 1.

 //       0 value & 1 == 0 //vs   value % 2 == 0 

Pengalaman pemrograman saya di Go tidak terlalu besar, hanya lebih dari satu setengah tahun, saya menggunakannya, meskipun sering, tetapi murni untuk tujuan utilitarian (well, mungkin kecuali untuk satu proyek yang terkait dengan layanan http yang sangat dimuat), jadi saya mulai dengan itu. Buka GoLand dan tulis tes sederhana

 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 } 

Kami mendapatkan hasil yang menunjukkan bahwa semakin tinggi ambang, semakin sering fluktuasi muncul dalam hal kinerja.

Bandingkan
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

Jelas bahwa dalam kasus ini, untuk ambang yang berbeda kami memiliki set data uji yang berbeda, beban prosesor (pada laptop i5-2540M saya) bervariasi sekitar 20,30%, memori yang ditempati oleh aplikasi yang berjalan dari GoLand rata-rata sekitar 813 MB - ini juga mempengaruhi keandalan hasil, Anda perlu menerapkan pelestarian suite uji pada disk dan menjalankan semua tes untuk setiap ambang pintu dalam isolasi satu sama lain.

Dan memikirkan bagaimana menerapkan semua ini dengan biaya minimal, saya secara otomatis memperbaiki cek kondisi

 if value > current && value&1 == 0 { current = value } 

pada

 if value <= current { continue; } if value&1 == 0 { current = value } 

Saya menjalankan tes lagi ... dan berhenti memahami sesuatu :)

Waktu yang dihabiskan untuk eksekusi mulai berbeda tidak lagi dengan persen / fraksi persen, tetapi dengan 10.,15% saya dengan cepat menambahkan 2 tes lagi:

 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 meluncurkan dan mendapatkan gambar ini:
kapasitas array awal: 100000000

ambang maksimal: 128
hasil maxEvenDividing: 126 durasi 116,0066ms
hasil maxEvenDividing2: 126 durasi 79,0045ms
Hasil maxEvenConjunction: 126 durasi 114,0065ms
hasil maxEvenConjunction2: 126 durasi 83,0048ms

ambang maksimal: 256
hasil maxEvenDividing: 254 durasi 111,0063ms
hasil maxEvenDividing2: 254 durasi 77,0044ms
Hasil maxEvenConjunction: 254 durasi 110,0063ms
Hasil maxEvenConjunction2: 254 durasi 80,0046ms

ambang maksimal: 512
Hasil maxEvenDividing: 510 durasi 114,0066ms
hasil maxEvenDividing2: 510 durasi 80.0045ms
Hasil maxEvenConjunction: 510 durasi 110,0063ms
Hasil maxEvenConjunction2: 510 durasi 80.0046ms

ambang maksimal: 1024
Hasil maxEvenDividing: durasi 1022 109,0063ms
hasil maxEvenDividing2: durasi 1022 77,0044ms
Hasil maxEvenConjunction: durasi 1022 111,0063ms
Hasil maxEvenConjunction2: durasi 1022 81,0047ms

ambang maksimal: 2048
Hasil maxEvenDividing: 2046 durasi 114,0065ms
hasil maxEvenDividing2: durasi 2046 79,0045ms
hasil maxEvenConjunction: durasi 2046 113,0065ms
hasil maxEvenConjunction2: durasi 2046 81,0046ms

ambang maksimal: 4096
maxEvenDividing hasil: durasi 4094 114,0065ms
hasil maxEvenDividing2: 4094 durasi 80.0046ms
Hasil maxEvenConjunction: durasi 4094 111,0063ms
Hasil maxEvenConjunction2: 4094 durasi 78,0045ms

ambang maksimal: 8192
hasil maxEvenDividing: durasi 8190 107,0062ms
hasil maxEvenDividing2: durasi 8190 77,0044ms
Hasil maxEvenConjunction: durasi 8190 111,0063ms
Hasil maxEvenConjunction2: durasi 8190 77,0044ms

ambang maksimal: 16384
hasil maxEvenDividing: durasi 16382 109,0063ms
hasil maxEvenDividing2: durasi 16382 77,0044ms
Hasil maxEvenConjunction: durasi 16382 108,0062ms
Hasil maxEvenConjunction2: durasi 16382 77,0044ms

ambang maksimal: 32768
Hasil maxEvenDividing: durasi 32766 112,0064ms
hasil maxEvenDividing2: durasi 32766 77,0044ms
hasil maxEvenConjunction: durasi 32766 109,0062ms
Hasil maxEvenConjunction2: 32766 durasi 78,0045ms

ambang maksimal: 65536
maxEvenDividing hasil: durasi 65534 109,0062ms
hasil maxEvenDividing2: 65534 durasi 75,0043ms
hasil maxEvenConjunction: durasi 65534 109,0063ms
Hasil maxEvenConjunction2: 65534 durasi 79,0045ms

ambang maksimal: 131072
hasil maxEvenDividing: durasi 131070 108,0061ms
hasil maxEvenDividing2: durasi 131070 76,0044ms
hasil maxEvenConjunction: durasi 131070 110,0063ms
Hasil maxEvenConjunction2: durasi 131070 80,0046ms

ambang maksimal: 262144
Hasil maxEvenDividing: 262142 durasi 110,0063ms
Hasil maxEvenDividing2: 262142 durasi 76,0044ms
Hasil maxEvenConjunction: 262142 durasi 107,0061ms
Hasil maxEvenConjunction2: 262142 durasi 78,0044ms

ambang maksimal: 524288
hasil maxEvenDividing: durasi 524286 109,0062ms
hasil maxEvenDividing2: durasi 524286 78,0045ms
Hasil maxEvenConjunction: durasi 524286 109,0062ms
Hasil maxEvenConjunction2: durasi 524286 80,0046ms

ambang maksimal: 1048576
Hasil maxEvenDividing: durasi 1048574 109,0063ms
hasil maxEvenDividing2: durasi 1048574 80,0045ms
Hasil maxEvenConjunction: durasi 1048574 114,0066ms
Hasil maxEvenConjunction2: 1048574 durasi 78,0044ms

ambang maksimal: 2097152
Hasil maxEvenDividing: 2097150 durasi 111,0064ms
hasil maxEvenDividing2: durasi 2097150 79,0045ms
Hasil maxEvenConjunction: 2097150 durasi 112,0064ms
Hasil maxEvenConjunction2: 2097150 durasi 77.0044ms

ambang maksimal: 4194304
Hasil maxEvenDividing: 4194302 durasi 111,0063ms
Hasil maxEvenDividing2: 4194302 durasi 78,0045ms
Hasil maxEvenConjunction: durasi 4194302 111,0063ms
Hasil maxEvenConjunction2: 4194302 durasi 77,0044ms

ambang maksimal: 8388608
Hasil maxEvenDividing: durasi 8388606 109,0062ms
maxEvenDividing2 hasil: 8388606 durasi 78,0045ms
Hasil maxEvenConjunction: durasi 8388606 114,0065ms
Hasil maxEvenConjunction2: 8388606 durasi 78,0045ms

ambang maksimal: 16777216
Hasil maxEvenDividing: durasi 16777214 109,0062ms
hasil maxEvenDividing2: durasi 16777214 77.0044ms
Hasil maxEvenConjunction: durasi 16777214 109,0063ms
Hasil maxEvenConjunction2: durasi 16777214 77.0044ms

ambang maksimal: 33554432
Hasil maxEvenDividing: 33554430 durasi 113.0065ms
hasil maxEvenDividing2: 33554430 durasi 78.0045ms
Hasil maxEvenConjunction: durasi 33554430 110,0063ms
Hasil maxEvenConjunction2: 33554430 durasi 80.0045ms

ambang maksimal: 67108864
hasil maxEvenDividing: durasi 67108860 112,0064ms
Hasil maxEvenDividing2: 67108860 durasi 77,0044ms
Hasil maxEvenConjunction: durasi 67108860 112,0064ms
Hasil maxEvenConjunction2: 67108860 durasi 80,0046ms

ambang maksimal: 134217728
Hasil maxEvenDividing: durasi 134217726 109,0063ms
Hasil maxEvenDividing2: durasi 134217726 78,0044ms
Hasil maxEvenConjunction: 134217726 durasi 114,0065ms
maxEvenConjunction2 hasil: durasi 134217726 81,0047ms

ambang maksimal: 268435456
Hasil maxEvenDividing: 268435446 durasi 111,0064ms
Hasil maxEvenDividing2: 268435446 durasi 79,0045ms
Hasil maxEvenConjunction: 268435446 durasi 114,0065ms
Hasil maxEvenConjunction2: 268435446 durasi 79,0045ms

ambang maksimal: 536870912
Hasil maxEvenDividing: durasi 536870910 107,0062ms
maxEvenDividing2 hasil: 536870910 durasi 76,0043ms
Hasil maxEvenConjunction: durasi 536870910 109,0062ms
maxEvenConjunction2 hasil: 536870910 durasi 80,0046ms

Penjelasan yang jelas tentang mengapa kompiler Go tidak mengoptimalkan kode dan selalu memeriksa kondisi kedua, bahkan jika yang pertama salah, saya tidak menemukan. Atau mungkin mata saya hanya "kabur" dan saya tidak melihat kesalahan yang jelas? Atau apakah Anda perlu menentukan beberapa instruksi khusus untuk kompiler? Saya akan senang dengan komentar yang masuk akal.

PS: Ya, untuk bersenang-senang, saya menjalankan tes serupa di Java 5 dan Java 7/8 - semuanya jelas, waktu pelaksanaannya sama.

Source: https://habr.com/ru/post/id444182/


All Articles