2 回答

TA貢獻1811條經(jīng)驗 獲得超5個贊
和 Max 一樣,我強烈懷疑 Go 的緩慢與糟糕的 I/O 性能有關(guān)。我測試了這個假設(shè):
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")
}
運行它產(chǎn)生了這個輸出:
在 2.011228ms 秒內(nèi)打開文件
在 109.904us 秒內(nèi)制作陣列
4.524544608s秒讀取數(shù)據(jù)
10.083329ms 秒內(nèi)處理的數(shù)據(jù)
1.703542918s秒輸出處理數(shù)據(jù)
所以看起來在我的機器上,所有的數(shù)學(xué)運算都發(fā)生在大約 10 毫秒內(nèi),但 I/O 很慢,證實了假設(shè)。正如 Janne 在評論中指出的那樣,可能有比fmt.
更新:例如,包裝input和outputwithbufio的讀者和作家:
binput := bufio.NewReader(input)
boutput := bufio.NewWriter(output)
使用binput和boutput緩沖 I/O,您的原始版本在我的機器上運行時間為 2.1 秒,比 Python 的 2.7 快一些。
更新 2:我注意到通過切換到緩沖 I/O 會得到不同的結(jié)果。
事實證明,您還需要調(diào)整格式字符串以包含\n,就像您在 C 版本中所做的那樣。我認為這實際上更正確,但看起來你可以在沒有緩沖的情況下逃脫。
這對Flush()你的緩沖輸出也很重要,我做了但之前沒有提到。
這是我完整的緩沖解決方案:
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\n",&ncases)
for i := 0; i < ncases; i++ {
fmt.Fscanf(binput, "%f\n", &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")
}

TA貢獻1853條經(jīng)驗 獲得超9個贊
我想以下幾行在 go 中工作得更慢。
fmt.Fscanf(input,"%f",&p) fmt.Fprintln(output,gain+10000)
當(dāng)你做 IO 時,Go 的魔法就會發(fā)生。它們看起來是同步的,但實際上它們是異步的。Go rotine 執(zhí)行異步請求并將控制權(quán)返回給調(diào)度程序。調(diào)度程序?qū)ふ伊硪粋€等待控制的 goroutine,但只有一個等待 io。所以調(diào)度器循環(huán)什么都不做。
如果您有 2、10 或 100 個并發(fā) goroutine,那么性能會更好。
- 2 回答
- 0 關(guān)注
- 204 瀏覽
添加回答
舉報