Live data from Hacker News

Comparing Pythagorean triples in C++, D, and Rust

atilanevesoncode.wordpress.com

21–30 of 118 posts

Re: Comparing Pythagorean triples in C++, D, and Rust

#22

The C++ version is taking a compile and runtime short cut by using printf instead of iostream. This pull request has timings with this changed: https://github.com/atilaneves/pythagoras/pull/1#issuecomment...

Using the stuff isn’t really idiomatic - on both modern and legacy code bases I’ve used operator<< overloads on custom types, but never called std::cout in a hot loop or used std::endl to do anything but actually flush the stream.

Re: Comparing Pythagorean triples in C++, D, and Rust

#23

The C++ version is taking a compile and runtime short cut by using printf instead of iostream. This pull request has timings with this changed: https://github.com/atilaneves/pythagoras/pull/1#issuecomment...

Yeah you also need to be careful mixing C++ and C iostream/stdio as there is synchronization if you mix them. And if you don't then you should use ` std::ios_base::sync_with_stdio(false);` to prevent performance issues.

Re: Comparing Pythagorean triples in C++, D, and Rust

#24

The C++ version is taking a compile and runtime short cut by using printf instead of iostream. This pull request has timings with this changed: https://github.com/atilaneves/pythagoras/pull/1#issuecomment...

Using the stuff isn’t really idiomatic - on both modern and legacy code bases I’ve used operator<< overloads on custom types, but never called std::cout in a hot loop or used std::endl to do anything but actually flush the stream.

What would you suggest is C++ recommended way for doing io?

Re: Comparing Pythagorean triples in C++, D, and Rust

#25

Earlier quoted context omitted.

Well, that seems more like an issue with the compiler then, cause avoiding overflows would not result in a 2x slow-down in C or C++.

Possibly! Remember that the Rust language and C/C++ have different semantics with regards to overflow. It may be the programmer's "fault" for not writing the code with the equivalent semantics (you can make them have the same semantics, but it's not the default).

Looking at the Rust source [1] it seems there the `next()` call has some overhead, so it's probably not the compiler.

I remember this was simple to implement in Julia [2] where you can iterate over the full range `for i = typemin(Int):typemax(Int) ... end` without overflow and without overhead. Same should be possible in Rust I think.

[1] https://doc.rust-lang.org/src/core/iter/range.rs.html#340-35...

[2] https://github.com/JuliaLang/julia/blob/master/base/range.jl...

Re: Comparing Pythagorean triples in C++, D, and Rust

#26

Update: The Rust versions can all be made to run faster with a simple edit. I've updated the timings and edited some of the text.

This was a really good and worthwhile analysis, thanks!

Despite the changes people are submitting, it's good to know about these different gotchas. And there may be one or two actual compiler enhancements that could be made here also.

Re: Comparing Pythagorean triples in C++, D, and Rust

#27
post #11

Earlier quoted context omitted.

I think you've seen this comment about integer overflow optimizations? https://www.reddit.com/r/rust/comments/ab7hsi/comparing_pyth... But I also note that the original version of your benchmark was calling `println!`, which means that you were essentially benchmarking high-level, thread-safe I/O. EDIT: Not in this case, see the thread below. Some Rust benchmarking tips: 1. Always run `cargo build --release`. Debug b…

> But I also note that the original version of your benchmark was calling `println!`, which means that you were essentially benchmarking high-level, thread-safe I/O. I don't think so. The program is only doing a thousand prints, which is far less than the total number of loop iterations. Try changing to locked stdout and writeln!---I doubt you'll notice a difference.

Yeah, I tried the locking version and didn't see a noticeable improvement.

Re: Comparing Pythagorean triples in C++, D, and Rust

#28
post #11
post #3

I would be really interested to know where the overhead in the simple rust version comes from. At first I thought it might be the println() being less efficient for whatever reason, but even without that line this[1] takes 300ms, compared to 184ms for this[2] (with the printf!). 1. https://raw.githubusercontent.com/atilaneves/pythagoras/mast... 2. https://raw.githubusercontent.com/atilaneves/pythagoras/mast...

I think you've seen this comment about integer overflow optimizations? https://www.reddit.com/r/rust/comments/ab7hsi/comparing_pyth... But I also note that the original version of your benchmark was calling `println!`, which means that you were essentially benchmarking high-level, thread-safe I/O. EDIT: Not in this case, see the thread below. Some Rust benchmarking tips: 1. Always run `cargo build --release`. Debug b…

I think the problem is flushing, not locking. Rust println!() flushes after each call, whereas more C-like io libraries flush once on program exit. Big difference in the number of system calls.

Re: Comparing Pythagorean triples in C++, D, and Rust

#29
post #28
post #11

Earlier quoted context omitted.

I think you've seen this comment about integer overflow optimizations? https://www.reddit.com/r/rust/comments/ab7hsi/comparing_pyth... But I also note that the original version of your benchmark was calling `println!`, which means that you were essentially benchmarking high-level, thread-safe I/O. EDIT: Not in this case, see the thread below. Some Rust benchmarking tips: 1. Always run `cargo build --release`. Debug b…

I think the problem is flushing, not locking. Rust println!() flushes after each call, whereas more C-like io libraries flush once on program exit. Big difference in the number of system calls.

EDIT: THIS IS ALL WRONG AND BACKWARDS, SEE BELOW

--------------------------

> Rust println!() flushes after each call,

To be clear, println! does not flush after each call.

Many terminals are line-buffered, and so when println! emits a \n, the terminal will flush. So, println! will probably cause a flush, but does not flush itself. println! is the exact same as `print!`, except for the additional printing of \n https://doc.rust-lang.org/stable/src/std/macros.rs.html#157-...

Re: Comparing Pythagorean triples in C++, D, and Rust

#30
post #9
post #3

I would be really interested to know where the overhead in the simple rust version comes from. At first I thought it might be the println() being less efficient for whatever reason, but even without that line this[1] takes 300ms, compared to 184ms for this[2] (with the printf!). 1. https://raw.githubusercontent.com/atilaneves/pythagoras/mast... 2. https://raw.githubusercontent.com/atilaneves/pythagoras/mast...

Someone found a single character change providing a 2x speedup: https://www.reddit.com/r/rust/comments/ab7hsi/comparing_pyth...

It's code quality problems with the inclusive-end range iterator.
Post reply on HN