前进条件及其奇数

您是否认为这两个用于检查循环条件的选项在性能上是否等效?

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上进行编程的经验不是很多,尽管有一年半的时间,但我经常使用它,但出于纯粹功利目的(好吧,也许除了与高负载http服务相关的一个项目),我才开始使用它。 打开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%,我很快又添加了两个测试:

 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
maxEven除法结果:126持续时间116.0066ms
maxEvenDividing2结果:126持续时间79.0045ms
maxEvenConjunction结果:126个持续时间114.0065ms
maxEvenConjunction2结果:126个持续时间83.0048ms

最大阈值:256
maxEven除法结果:254持续时间111.0063ms
maxEvenDividing2结果:254持续时间77.0044ms
maxEvenConjunction结果:254持续时间110.0063ms
maxEvenConjunction2结果:254持续时间80.0046ms

最大阈值:512
maxEven除法结果:510持续时间114.0066ms
maxEvenDividing2结果:510持续时间80.0045ms
maxEvenConjunction结果:510持续时间110.0063ms
maxEvenConjunction2结果:510持续时间80.0046ms

最大阈值:1024
maxEven除法结果:1022持续时间109.0063ms
maxEvenDividing2结果:1022持续时间77.0044ms
maxEvenConjunction结果:1022持续时间111.0063ms
maxEvenConjunction2结果:1022持续时间81.0047ms

最大阈值:2048
maxEven除法结果:2046持续时间114.0065ms
maxEvenDividing2结果:2046时长79.0045ms
maxEvenConjunction结果:2046持续时间113.0065ms
maxEvenConjunction2结果:2046持续时间81.0046ms

最大阈值:4096
maxEven除法结果:4094持续时间114.0065ms
maxEvenDividing2结果:4094持续时间80.0046ms
maxEvenConjunction结果:4094持续时间111.0063ms
maxEvenConjunction2结果:4094持续时间78.0045ms

最大阈值:8192
maxEven除法结果:8190持续时间107.0062ms
maxEvenDividing2结果:8190持续时间77.0044ms
maxEvenConjunction结果:8190持续时间111.0063ms
maxEvenConjunction2结果:8190持续时间77.0044ms

最大阈值:16384
maxEven除法结果:16382持续时间109.0063ms
maxEvenDividing2结果:16382持续时间77.0044ms
maxEvenConjunction结果:16382持续时间108.0062ms
maxEvenConjunction2结果:16382持续时间77.0044ms

最大阈值:32768
maxEven除法结果:32766持续时间112.0064ms
maxEvenDividing2结果:32766持续时间77.0044ms
maxEvenConjunction结果:32766持续时间109.0062ms
maxEvenConjunction2结果:32766持续时间78.0045ms

最大阈值:65536
maxEven除法结果:65534持续时间109.0062ms
maxEvenDividing2结果:65534持续时间75.0043ms
maxEvenConjunction结果:65534持续时间109.0063ms
maxEvenConjunction2结果:65534持续时间79.0045ms

最大阈值:131072
maxEven除法结果:131070持续时间108.0061ms
maxEvenDividing2结果:131070持续时间76.0044ms
maxEvenConjunction结果:131070持续时间110.0063ms
maxEvenConjunction2结果:131070持续时间80.0046ms

最大阈值:262144
maxEven除法结果:262142持续时间110.0063ms
maxEvenDividing2结果:262142持续时间76.0044ms
maxEvenConjunction结果:262142持续时间107.0061ms
maxEvenConjunction2结果:262142持续时间78.0044ms

最大阈值:524288
maxEven除法结果:524286持续时间109.0062ms
maxEvenDividing2结果:524286持续时间78.0045ms
maxEvenConjunction结果:524286持续时间109.0062ms
maxEvenConjunction2结果:524286持续时间80.0046ms

最大阈值:1048576
maxEven除法结果:1048574持续时间109.0063ms
maxEvenDividing2结果:1048574持续时间80.0045ms
maxEvenConjunction结果:1048574持续时间114.0066ms
maxEvenConjunction2结果:1048574持续时间78.0044ms

最大阈值:2097152
maxEven除法结果:2097150持续时间111.0064ms
maxEvenDividing2结果:2097150持续时间79.0045ms
maxEvenConjunction结果:2097150持续时间112.0064ms
maxEvenConjunction2结果:2097150持续时间77.0044ms

最大阈值:4194304
maxEven除法结果:4194302持续时间111.0063ms
maxEvenDividing2结果:4194302持续时间78.0045ms
maxEvenConjunction结果:4194302持续时间111.0063ms
maxEvenConjunction2结果:4194302持续时间77.0044ms

最大阈值:8388608
maxEven除法结果:8388606持续时间109.0062ms
maxEvenDividing2结果:8388606持续时间78.0045ms
maxEvenConjunction结果:8388606持续时间114.0065ms
maxEvenConjunction2结果:8388606持续时间78.0045ms

最大阈值:16777216
maxEven除法结果:16777214持续时间109.0062ms
maxEvenDividing2结果:16777214持续时间77.0044ms
maxEvenConjunction结果:16777214持续时间109.0063ms
maxEvenConjunction2结果:16777214持续时间77.0044ms

最大阈值:33554432
maxEven除法结果:33554430持续时间113.0065ms
maxEvenDividing2结果:33554430持续时间78.0045ms
maxEvenConjunction结果:33554430持续时间110.0063ms
maxEvenConjunction2结果:33554430持续时间80.0045ms

最大阈值:67108864
maxEven除法结果:67108860持续时间112.0064ms
maxEvenDividing2结果:67108860持续时间77.0044ms
maxEvenConjunction结果:67108860持续时间112.0064ms
maxEvenConjunction2结果:67108860持续时间80.0046ms

最大阈值:134217728
maxEven除法结果:134217726持续时间109.0063ms
maxEvenDividing2结果:134217726持续时间78.0044ms
maxEvenConjunction结果:134217726持续时间114.0065ms
maxEvenConjunction2结果:134217726持续时间81.0047ms

最大阈值:268435456
maxEven除法结果:268435446持续时间111.0064ms
maxEvenDividing2结果:268435446持续时间79.0045ms
maxEvenConjunction结果:268435446持续时间114.0065ms
maxEvenConjunction2结果:268435446持续时间79.0045ms

最大阈值:536870912
maxEven除法结果:536870910持续时间107.0062ms
maxEvenDividing2结果:536870910持续时间76.0043ms
maxEvenConjunction结果:536870910持续时间109.0062ms
maxEvenConjunction2结果:536870910持续时间80.0046ms

清楚说明了为什么Go编译器不优化代码并始终检查第二个条件,即使第一个条件为假,我也没有找到。 还是我的眼睛只是“模糊”,我看不到任何明显的错误? 还是需要为编译器指定一些特殊指令? 我会对明智的评论感到满意。

PS:是的,为了娱乐,我在Java 5和Java 7/8上进行了类似的测试-一切都很清楚,执行时间是相同的。

Source: https://habr.com/ru/post/zh-CN444182/


All Articles