Max のように、Go の遅さは I/O パフォーマンスの低さに関係しているのではないかと強く疑っていました。私はこの仮説をテストしました:
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")
}
実行すると、次の出力が生成されました。
2.011228ms でファイルを開きました
109.904us 秒でアレイを作成
4.524544608 秒でデータを読み取る
10.083329ms 秒でデータを処理
1.703542918秒で処理済みデータを出力
したがって、私のマシンでは、すべての計算が約 10 ミリ秒で行われるように見えますが、I/O は遅く、仮説を裏付けています。Janne がコメントで指摘したように、より高速なオプションが存在する可能性がありますfmt
。
更新:たとえば、のリーダーinput
とライターoutput
を使用したラッピング:bufio
binput := bufio.NewReader(input)
boutput := bufio.NewWriter(output)
およびバッファリングされた I/O を使用するbinput
とboutput
、元のバージョンは私のマシンで 2.1 秒で実行され、Python の 2.7 よりもいくらか高速です。
更新 2:バッファー I/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")
}