{"author":{"address":null,"user":"https://learnblockchain.cn/people/4993"},"content":{"body":"最近遇到一个有趣的问题，有人在测试Rust的性能的时候发现Rust比Golang慢竟然一倍。\r\n```shell\r\nProject             Execution Time (s)\r\nRust                2.9696159\r\nGo                  1.981306\r\n```\r\n并且评论中大部分人都认为是多线程代码中的Mutex导致，但是根据我初步分析来看，和Mutex完全没用关系。\r\n代码如下。\r\nhttps://github.com/nishuzumi/rust-vs-golang/blob/main/sin-cos/rust/src/main.rs\r\n```rust\r\nuse num_cpus;\r\nuse std::{\r\n    sync::{Arc, Mutex},\r\n    thread,\r\n};\r\n\r\nuse std::time::Instant;\r\nfn main() {\r\n    let num_cpus = num_cpus::get();\r\n    let start_time = Instant::now();\r\n\r\n    let mut handles = vec![];\r\n    let result = Arc::new(Mutex::new(vec![0.0; num_cpus]));\r\n\r\n    for i in 0..num_cpus {\r\n        let result = Arc::clone(\u0026result);\r\n        let handle = thread::spawn(move || {\r\n            let mut local_result = 0.0;\r\n            for j in 0..100_000_000 {\r\n                local_result += (j as f64).sin() * (j as f64).cos();\r\n            }\r\n\r\n            let mut result = result.lock().unwrap();\r\n            result[i] = local_result;\r\n            println!(\"Thread {} result: {}\", i, local_result);\r\n        });\r\n        handles.push(handle);\r\n    }\r\n\r\n    for handle in handles {\r\n        handle.join().unwrap();\r\n    }\r\n\r\n    let final_result = result.lock().unwrap().iter().sum::\u003cf64\u003e();\r\n\r\n    println!(\"Elapsed time: {:?}\", start_time.elapsed().as_secs_f64());\r\n    println!(\"Final result: {}\", final_result);\r\n}\r\n```\r\n而Golang部分的代码如下\r\nhttps://github.com/nishuzumi/rust-vs-golang/blob/main/sin-cos/golang/main.go\r\n```golang\r\npackage main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"math\"\r\n\t\"runtime\"\r\n\t\"sync\"\r\n\t\"time\"\r\n)\r\n\r\nfunc main() {\r\n\tnumCPU := runtime.NumCPU()\r\n\tfmt.Printf(\"Running with %d CPUs\\n\", numCPU)\r\n\r\n\tvar wg sync.WaitGroup\r\n\r\n\tstart := time.Now()\r\n\r\n\tfor i := 0; i \u003c numCPU; i++ {\r\n\t\twg.Add(1)\r\n\t\tgo func(id int) {\r\n\t\t\tdefer wg.Done()\r\n\t\t\tresult := 0.0\r\n\t\t\tfor j := 0; j \u003c 1e8; j++ {\r\n\t\t\t\tresult += math.Sin(float64(j)) * math.Cos(float64(j))\r\n\t\t\t}\r\n\t\t\tfmt.Printf(\"Goroutine %d result: %f\\n\", id, result)\r\n\t\t}(i)\r\n\t}\r\n\r\n\twg.Wait()\r\n\r\n\telapsed := time.Since(start)\r\n\tfmt.Printf(\"Elapsed time: %f\\n\", elapsed.Seconds())\r\n}\r\n```\r\n\r\n初步分析来看，rust虽然用了一个毫无必要的锁，但是这个锁并没有堵塞线程的迹象。而运行出来的结果是。\r\n```shell\r\nProject             Execution Time (s)\r\nRust                2.9696159\r\nGo                  1.981306\r\n```\r\n很明显，Rust的速度反而没有Golang快，慢了一秒。这是为什么呢？可以思考一下 马上揭晓答案。\r\n\r\n### 答案\r\n原因在于Window上的一些小问题，以上代码在Linux和macos下运行的速度是正常的，golang比rust慢。\r\n\r\n主要原因是，golang的math仓库是另外一套实现，而rust使用的是libm进行计算。在同样的环境下c++和rust的速度基本一致。而golang的math实现虽然快，但是损失了精度，详细可以见这里的解释。\r\nhttps://github.com/nishuzumi/rust-vs-golang/blob/main/sin-cos/readme.md\r\n\r\n### 结尾\r\n最近发现了很多这样的速度差异对比，我感觉很有意思，于是创建了一个仓库，用于记录这些差别。\r\n\r\nhttps://github.com/nishuzumi/rust-vs-golang\r\n\r\n如果你也有一些速度差异的例子，欢迎到Github中进行补充。","title":"Rust多线程浮点数运算比Golang慢一倍？"},"history":null,"timestamp":1722081331,"version":1}