C++ 范围/视图 vs. Rust 迭代器

2作者: bijan75 个月前原帖
似乎Rust的迭代器性能与C++的范围/视图之间存在相当大的差距,除非我遗漏了什么。 Rust代码: ```rust use std::time::Instant; fn expand_iota_views(input: &[i32]) -> impl Iterator<Item = i32> + '_ { input .iter() .flat_map(|&n| 1..=n) .flat_map(|n| 1..=n) .flat_map(|n| 1..=n) } fn main() { let input: Vec<i32> = (0..=50).collect(); let sample_result: Vec<i32> = expand_iota_views(&input).collect(); println!("Rust Result count: {}", sample_result.len()); let start = Instant::now(); let mut total_count = 0; for _ in 0..1000 { let result = expand_iota_views(&input); total_count += result.count(); } let duration = start.elapsed(); println!("Rust Total count (1000 iterations): {}", total_count); println!("Rust Total time: {} microseconds", duration.as_micros()); println!( "Rust Average per iteration: {:.2} microseconds", duration.as_micros() as f64 / 1000.0 ); } ``` 输出: ``` Rust Result count: 292825 Rust Total count (1000 iterations): 292825000 Rust Total time: 1025 microseconds Rust Average per iteration: 1.02 microseconds ``` C++代码: ```cpp #include <chrono> #include <iostream> #include <numeric> #include <ranges> #include <vector> inline auto expandIotaViews(const std::vector<int>& input) { auto iota_transform = [](const int number) { return std::views::iota(1, number + 1); }; return input | std::views::transform(iota_transform) | std::views::join | std::views::transform(iota_transform) | std::views::join | std::views::transform(iota_transform) | std::views::join; } int main() { std::vector<int> input(51); std::iota(input.begin(), input.end(), 0); auto sample_result = expandIotaViews(input); std::vector<int> result_vec; for (auto val : sample_result) { result_vec.push_back(val); } std::cout << "C++ Result count: " << result_vec.size() << std::endl; auto start = std::chrono::high_resolution_clock::now(); size_t total_count = 0; for (int i = 0; i < 1000; ++i) { auto result = expandIotaViews(input); total_count += std::ranges::distance(result); } auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start); std::cout << "C++ Total count (1000 iterations): " << total_count << std::endl; std::cout << "C++ Total time: " << duration.count() << " microseconds" << std::endl; std::cout << "C++ Average per iteration: " << duration.count() / 1000.0 << " microseconds" << std::endl; return 0; } ``` 输出: ``` C++ Result count: 292825 C++ Total count (1000 iterations): 292825000 C++ Total time: 174455 microseconds C++ Average per iteration: 174.455 microseconds ```
查看原文
it seems there is a quite a bit of gap between the performance of Rust iterator and C++ ranges&#x2F;views unless I am missing something.<p>https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;v76rcEb9n https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;YG1dv4qYh<p>Rust: &lt;code&gt; use std::time::Instant;<p>fn expand_iota_views(input: &amp;[i32]) -&gt; impl Iterator&lt;Item = i32&gt; + &#x27;_ { input .iter() .flat_map(|&amp;n| 1..=n) .flat_map(|n| 1..=n) .flat_map(|n| 1..=n) }<p>fn main() { let input: Vec&lt;i32&gt; = (0..=50).collect();<p><pre><code> let sample_result: Vec&lt;i32&gt; = expand_iota_views(&amp;input).collect(); println!(&quot;Rust Result count: {}&quot;, sample_result.len()); let start = Instant::now(); let mut total_count = 0; for _ in 0..1000 { let result = expand_iota_views(&amp;input); total_count += result.count(); } let duration = start.elapsed(); println!(&quot;Rust Total count (1000 iterations): {}&quot;, total_count); println!(&quot;Rust Total time: {} microseconds&quot;, duration.as_micros()); println!( &quot;Rust Average per iteration: {:.2} microseconds&quot;, duration.as_micros() as f64 &#x2F; 1000.0 );</code></pre> } &lt;&#x2F;code&gt;<p>Output: Rust Result count: 292825 Rust Total count (1000 iterations): 292825000 Rust Total time: 1025 microseconds Rust Average per iteration: 1.02 microseconds<p>C++: &lt;code&gt; #include &lt;chrono&gt; #include &lt;iostream&gt; #include &lt;numeric&gt; #include &lt;ranges&gt; #include &lt;vector&gt;<p>inline auto expandIotaViews(const std::vector&lt;int&gt;&amp; input) { auto iota_transform = [](const int number) { return std::views::iota(1, number + 1); };<p><pre><code> return input | std::views::transform(iota_transform) | std::views::join | std::views::transform(iota_transform) | std::views::join | std::views::transform(iota_transform) | std::views::join;</code></pre> }<p>int main() { std::vector&lt;int&gt; input(51); std::iota(input.begin(), input.end(), 0);<p><pre><code> auto sample_result = expandIotaViews(input); std::vector&lt;int&gt; result_vec; for (auto val : sample_result) { result_vec.push_back(val); } std::cout &lt;&lt; &quot;C++ Result count: &quot; &lt;&lt; result_vec.size() &lt;&lt; std::endl; auto start = std::chrono::high_resolution_clock::now(); size_t total_count = 0; for (int i = 0; i &lt; 1000; ++i) { auto result = expandIotaViews(input); total_count += std::ranges::distance(result); } auto end = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast&lt;std::chrono::microseconds&gt;(end - start); std::cout &lt;&lt; &quot;C++ Total count (1000 iterations): &quot; &lt;&lt; total_count &lt;&lt; std::endl; std::cout &lt;&lt; &quot;C++ Total time: &quot; &lt;&lt; duration.count() &lt;&lt; &quot; microseconds&quot; &lt;&lt; std::endl; std::cout &lt;&lt; &quot;C++ Average per iteration: &quot; &lt;&lt; duration.count() &#x2F; 1000.0 &lt;&lt; &quot; microseconds&quot; &lt;&lt; std::endl; return 0;</code></pre> } &lt;&#x2F;code&gt;<p>Output: C++ Result count: 292825 C++ Total count (1000 iterations): 292825000 C++ Total time: 174455 microseconds C++ Average per iteration: 174.455 microseconds