Amodau yn Go a'u quirks

Ydych chi'n meddwl bod y ddau opsiwn hyn ar gyfer profi amodau y tu mewn i ddolen yn cyfateb o ran perfformiad?

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


Dechreuodd y cyfan gyda β€œcynhesu'r ymennydd”; roedd yn rhaid i mi roi enghraifft o'r chwiliad gorau posibl am yr eilrif mwyaf mewn amrywiaeth o gyfanrifau [-x....x]. Roeddwn yn meddwl tybed faint fyddai perfformiad gwell pe bawn yn defnyddio lluosi rhesymegol ag 1 i ddarganfod a yw rhif yn eilrif ai peidio.


//Ρƒ Ρ‡Π΅Ρ‚Π½Ρ‹Ρ… чисСл послСдний Π±ΠΈΡ‚ всСгда Ρ€Π°Π²Π΅Π½ 0
value & 1 == 0
//vs классичСский ΠΌΠ΅Ρ‚ΠΎΠ΄
value % 2 == 0

Nid yw fy mhrofiad rhaglennu yn Go yn helaeth iawn, ychydig dros flwyddyn a hanner, defnyddiais ef, er yn aml, ond at ddibenion iwtilitaraidd yn unig (wel, efallai heblaw am un prosiect yn ymwneud Γ’ gwasanaeth http llwyth uchel), felly fe wnes i dechrau ag ef. Agor GoLand ac ysgrifennu prawf syml


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
}

Cawn ganlyniad sy'n dangos po uchaf yw'r trothwy, y mwyaf aml y mae amrywiadau mewn perfformiad yn ymddangos.

Cymharwchmax 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

Mae'n amlwg, yn yr achos hwn, ar gyfer gwahanol drothwyon mae gennym setiau gwahanol o ddata prawf, mae llwyth y prosesydd (ar fy ngliniadur i5-2540M) yn amrywio o gwmpas 20..30%, mae'r cof a feddiannir gan y cymhwysiad sy'n rhedeg o GoLand ar gyfartaledd tua 813MB - mae hyn hefyd yn effeithio ar ddibynadwyedd y canlyniad, mae angen i chi arbed achosion prawf ar ddisg a rhedeg yr holl brofion ar gyfer pob trothwy ar wahΓ’n i'w gilydd.

Ac yn awr, gan feddwl am sut i weithredu hyn i gyd heb fawr o gostau, rwy'n cywiro'r gwiriad cyflwr yn awtomatig

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

ar

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

Rwy'n rhedeg y profion eto ... a dwi'n stopio deall unrhyw beth :)

Nid yw'r amser a dreulir ar ddienyddio yn dechrau amrywio bellach yn Γ΄l canrannau/ffracsiynau o y cant, ond 10..15% Rwy'n ychwanegu 2 brawf arall yn gyflym:

		
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
}

Rwy'n ei redeg ac yn cael y llun hwn:capasiti arae cychwynnol: 100000000

trothwy uchaf: 128
maxEvenDividing canlyniad: 126 hyd 116.0066ms
canlyniad maxEvenDividing2: 126 hyd 79.0045ms
maxEvenConjunction canlyniad: 126 hyd 114.0065ms
maxEvenConjunction2 canlyniad: 126 hyd 83.0048ms

trothwy uchaf: 256
maxEvenDividing canlyniad: 254 hyd 111.0063ms
canlyniad maxEvenDividing2: 254 hyd 77.0044ms
maxEvenConjunction canlyniad: 254 hyd 110.0063ms
maxEvenConjunction2 canlyniad: 254 hyd 80.0046ms

trothwy uchaf: 512
maxEvenDividing canlyniad: 510 hyd 114.0066ms
canlyniad maxEvenDividing2: 510 hyd 80.0045ms
maxEvenConjunction canlyniad: 510 hyd 110.0063ms
maxEvenConjunction2 canlyniad: 510 hyd 80.0046ms

trothwy uchaf: 1024
maxEvenDividing canlyniad: 1022 hyd 109.0063ms
canlyniad maxEvenDividing2: 1022 hyd 77.0044ms
maxEvenConjunction canlyniad: 1022 hyd 111.0063ms
maxEvenConjunction2 canlyniad: 1022 hyd 81.0047ms

trothwy uchaf: 2048
maxEvenDividing canlyniad: 2046 hyd 114.0065ms
canlyniad maxEvenDividing2: 2046 hyd 79.0045ms
maxEvenConjunction canlyniad: 2046 hyd 113.0065ms
maxEvenConjunction2 canlyniad: 2046 hyd 81.0046ms

trothwy uchaf: 4096
maxEvenDividing canlyniad: 4094 hyd 114.0065ms
canlyniad maxEvenDividing2: 4094 hyd 80.0046ms
maxEvenConjunction canlyniad: 4094 hyd 111.0063ms
maxEvenConjunction2 canlyniad: 4094 hyd 78.0045ms

trothwy uchaf: 8192
maxEvenDividing canlyniad: 8190 hyd 107.0062ms
canlyniad maxEvenDividing2: 8190 hyd 77.0044ms
maxEvenConjunction canlyniad: 8190 hyd 111.0063ms
maxEvenConjunction2 canlyniad: 8190 hyd 77.0044ms

trothwy uchaf: 16384
maxEvenDividing canlyniad: 16382 hyd 109.0063ms
canlyniad maxEvenDividing2: 16382 hyd 77.0044ms
maxEvenConjunction canlyniad: 16382 hyd 108.0062ms
maxEvenConjunction2 canlyniad: 16382 hyd 77.0044ms

trothwy uchaf: 32768
maxEvenDividing canlyniad: 32766 hyd 112.0064ms
canlyniad maxEvenDividing2: 32766 hyd 77.0044ms
maxEvenConjunction canlyniad: 32766 hyd 109.0062ms
maxEvenConjunction2 canlyniad: 32766 hyd 78.0045ms

trothwy uchaf: 65536
maxEvenDividing canlyniad: 65534 hyd 109.0062ms
canlyniad maxEvenDividing2: 65534 hyd 75.0043ms
maxEvenConjunction canlyniad: 65534 hyd 109.0063ms
maxEvenConjunction2 canlyniad: 65534 hyd 79.0045ms

trothwy uchaf: 131072
maxEvenDividing canlyniad: 131070 hyd 108.0061ms
canlyniad maxEvenDividing2: 131070 hyd 76.0044ms
maxEvenConjunction canlyniad: 131070 hyd 110.0063ms
maxEvenConjunction2 canlyniad: 131070 hyd 80.0046ms

trothwy uchaf: 262144
maxEvenDividing canlyniad: 262142 hyd 110.0063ms
canlyniad maxEvenDividing2: 262142 hyd 76.0044ms
maxEvenConjunction canlyniad: 262142 hyd 107.0061ms
maxEvenConjunction2 canlyniad: 262142 hyd 78.0044ms

trothwy uchaf: 524288
maxEvenDividing canlyniad: 524286 hyd 109.0062ms
canlyniad maxEvenDividing2: 524286 hyd 78.0045ms
maxEvenConjunction canlyniad: 524286 hyd 109.0062ms
maxEvenConjunction2 canlyniad: 524286 hyd 80.0046ms

trothwy uchaf: 1048576
maxEvenDividing canlyniad: 1048574 hyd 109.0063ms
canlyniad maxEvenDividing2: 1048574 hyd 80.0045ms
maxEvenConjunction canlyniad: 1048574 hyd 114.0066ms
maxEvenConjunction2 canlyniad: 1048574 hyd 78.0044ms

trothwy uchaf: 2097152
maxEvenDividing canlyniad: 2097150 hyd 111.0064ms
canlyniad maxEvenDividing2: 2097150 hyd 79.0045ms
maxEvenConjunction canlyniad: 2097150 hyd 112.0064ms
maxEvenConjunction2 canlyniad: 2097150 hyd 77.0044ms

trothwy uchaf: 4194304
maxEvenDividing canlyniad: 4194302 hyd 111.0063ms
canlyniad maxEvenDividing2: 4194302 hyd 78.0045ms
maxEvenConjunction canlyniad: 4194302 hyd 111.0063ms
maxEvenConjunction2 canlyniad: 4194302 hyd 77.0044ms

trothwy uchaf: 8388608
maxEvenDividing canlyniad: 8388606 hyd 109.0062ms
canlyniad maxEvenDividing2: 8388606 hyd 78.0045ms
maxEvenConjunction canlyniad: 8388606 hyd 114.0065ms
maxEvenConjunction2 canlyniad: 8388606 hyd 78.0045ms

trothwy uchaf: 16777216
maxEvenDividing canlyniad: 16777214 hyd 109.0062ms
canlyniad maxEvenDividing2: 16777214 hyd 77.0044ms
maxEvenConjunction canlyniad: 16777214 hyd 109.0063ms
maxEvenConjunction2 canlyniad: 16777214 hyd 77.0044ms

trothwy uchaf: 33554432
maxEvenDividing canlyniad: 33554430 hyd 113.0065ms
canlyniad maxEvenDividing2: 33554430 hyd 78.0045ms
maxEvenConjunction canlyniad: 33554430 hyd 110.0063ms
maxEvenConjunction2 canlyniad: 33554430 hyd 80.0045ms

trothwy uchaf: 67108864
maxEvenDividing canlyniad: 67108860 hyd 112.0064ms
canlyniad maxEvenDividing2: 67108860 hyd 77.0044ms
maxEvenConjunction canlyniad: 67108860 hyd 112.0064ms
maxEvenConjunction2 canlyniad: 67108860 hyd 80.0046ms

trothwy uchaf: 134217728
maxEvenDividing canlyniad: 134217726 hyd 109.0063ms
canlyniad maxEvenDividing2: 134217726 hyd 78.0044ms
maxEvenConjunction canlyniad: 134217726 hyd 114.0065ms
maxEvenConjunction2 canlyniad: 134217726 hyd 81.0047ms

trothwy uchaf: 268435456
maxEvenDividing canlyniad: 268435446 hyd 111.0064ms
canlyniad maxEvenDividing2: 268435446 hyd 79.0045ms
maxEvenConjunction canlyniad: 268435446 hyd 114.0065ms
maxEvenConjunction2 canlyniad: 268435446 hyd 79.0045ms

trothwy uchaf: 536870912
maxEvenDividing canlyniad: 536870910 hyd 107.0062ms
canlyniad maxEvenDividing2: 536870910 hyd 76.0043ms
maxEvenConjunction canlyniad: 536870910 hyd 109.0062ms
maxEvenConjunction2 canlyniad: 536870910 hyd 80.0046ms

Ni allwn ddod o hyd i esboniad clir pam nad yw'r casglwr Go yn gwneud y gorau o'r cod ac yn gwirio'r ail amod bob amser, hyd yn oed os yw'r un cyntaf yn ffug. Neu efallai bod fy llygaid yn aneglur ac nid wyf yn gweld unrhyw gamgymeriad amlwg? Neu a oes angen i chi ddarparu rhai cyfarwyddiadau arbennig i'r casglwr? Byddwn yn falch o gael sylwadau synhwyrol.

PS: Ydw, dim ond am hwyl, cynhaliais brofion tebyg ar Java 5 a Java 7/8 - mae popeth yn glir, mae'r amser gweithredu yr un peth.

Ffynhonnell: hab.com

Ychwanegu sylw