dougaimian1143 2013-06-20 08:26
浏览 7
已采纳

在以下情况下,为什么Go程序的性能比预期的要差得多? [关闭]

I was solving a simple question in C, Go, and Python and comparing the results. The solution is simply supposed to have two equations inside an if-else block. The following are the code for my solution in:

C

python

go

I was comparing the way the three languages deal with floating point results and hence made this script to generate the test cases and this to compare the results, two at a time.

The weird thing is the time it takes to run the first 3 scripts. The C program obviously runs within a couple of seconds. Python takes around 2.5-3 seconds. However, Go is taking around 24-25 seconds to run the program on the test cases generated by the generate_test_cases.py script.

I thought Go would be somewhere between C and Python as far as running time is concerned. Am I doing something inefficiently with my Go code, and if so, what?

P.S. I also ran the above three programs without the file handling operations, and still the same result, i.e., Go takes an extraordinarily long time compared to the other two.

  • 写回答

2条回答 默认 最新

  • dtlab08822 2013-06-20 09:07
    关注

    Like Max, my strong suspicion was that the slowness in Go was related to poor I/O performance. I tested this hypothesis:

    package main
    
    import "fmt"
    import "os"
    import "time"
    
    func main(){
        now := time.Now()
        input,_ := os.Open("testing/test_cases.txt")
        defer input.Close()
        output,_ := os.Create("testing/Goutput.txt")
        defer output.Close()
    
        var ncases int
        var p float64
        fmt.Fscanf(input,"%d",&ncases)
    
        fmt.Println("Opened files in ", time.Since(now), "seconds")
        now = time.Now()
    
        cases := make([]float64, ncases)
        fmt.Println("Made array in ", time.Since(now), "seconds")
        now = time.Now()
    
        for i := 0; i < ncases; i++ {
            fmt.Fscanf(input,"%f",&cases[i])
        }
    
        fmt.Println("Read data in ", time.Since(now), "seconds")
        now = time.Now()
    
        for i := 0; i < ncases; i++ {
            p = cases[i]
            if p >= 0.5 {
                cases[i] = 10000 * (1-p) * (2*p-1) + 10000
            } else {
                cases[i] = p*(1-2*p)*10000 + 10000
            }
        }
    
        fmt.Println("Processed data in ", time.Since(now), "seconds")
        now = time.Now()
    
        for i := 0; i < ncases; i++ {
            fmt.Fprintln(output, cases[i])
        }
    
        fmt.Println("Output processed data in ", time.Since(now), "seconds")
    }
    

    Running it produced this output:

    Opened files in  2.011228ms seconds
    Made array in  109.904us seconds
    Read data in  4.524544608s seconds
    Processed data in  10.083329ms seconds
    Output processed data in  1.703542918s seconds
    

    So it appears that on my machine, all of the math occurs in about 10ms, but the I/O is slow, confirming the hypothesis. As pointed out by Janne in the comments, there are likely faster options than fmt.

    Update: For example, wrapping input and output with bufio's Readers and Writers:

    binput := bufio.NewReader(input)
    boutput := bufio.NewWriter(output)
    

    and using binput and boutput for buffered I/O, your original version runs in 2.1 seconds on my machine, somewhat faster than Python's 2.7.

    Update 2: I noticed that I was getting different results by just switching to buffered I/O.

    1. It turns out that you also need to adjust your format strings to include the , as you do in the C version. I think this is actually more correct either way, but it looks like you can get away with it while unbuffered.

    2. It's also important to Flush() your buffered output, which I did but didn't mention before.

    Here's my complete buffered solution:

    package main
    
    import "fmt"
    import "os"
    import "bufio"
    import "time"
    
    func main(){
        now := time.Now()
    
        nbinput, _ := os.Open("testing/test_cases.txt")
        defer nbinput.Close()
    
        nboutput, _ := os.Create("testing/Goutput.txt")
        defer nboutput.Close()
    
        binput := bufio.NewReader(nbinput)
        boutput := bufio.NewWriter(nboutput)
    
        var ncases int
        var gain, p float64
        fmt.Fscanf(binput,"%d
    ",&ncases)
    
        for i := 0; i < ncases; i++ {
            fmt.Fscanf(binput, "%f
    ", &p)
            if p >= 0.5 {
                gain = 10000 * (1-p) * (2*p -1)
            } else {
                gain = p*(1-2*p)*10000
            }
            fmt.Fprintln(boutput, gain+10000)
        }
        boutput.Flush()
        fmt.Println("Took ", time.Since(now), "seconds")
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥120 计算机网络的新校区组网设计
  • ¥20 完全没有学习过GAN,看了CSDN的一篇文章,里面有代码但是完全不知道如何操作
  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 海浪数据 南海地区海况数据,波浪数据
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?