Closed koutoftimer closed 4 years ago
Thanks, that's quite fast!
I like to have a generic parse()
that applies to a variety of types. On integer types, it redirects to from_str_radix()
. Maybe all the checked adds and multiplies are what's slowing it down?
I think contest problems generally can handle the overhead, but traits and macros could be used to defer certain types if you'd like the speed of handcoded implementations. A standard library solution just feels a bit safer to me. Even UnsafeScanner
's only assumption is that the input be valid UTF-8, which is true for all programming contests of which I'm aware; in fact, they only use the ASCII subset.
I agree that it is better to stay generic, but I almost lost my hope in this approach because of Problem B on Codeforces.
Writing output is even slower than reading input data. Datastructures like Vec<i32>
, even made via ::with_capacity
constructor are too much slow..
It took me 8 tried to complete solution. Despite it was good playgroud, I'm still a bit disapointed that Rust with opt-level=0
is SO SLOW with I\O and all kinds of checks (like overflows for each numeric operation).
What I discovered:
std
is pretty much always faster than handmade calculations with for
loops because of additional checks made for opt-level=0
.Vec
data structure is slower then regular arrays.Do you know some tips how to stay generic and do not loose performance on opt-leve=0
? IMHO, asking rust community sounds stupid, because they can asnwer something like "we have opt-level=3
for speed optimized builds" (which is really damn fast).
UPD: Note: I haven't mentioned, that when I talk about "regular array" I mean stack allocated. Heap allocation for large vectors takes a lot of time in comparison to arrays on stack.
Wow 1000 ms to 78 ms! That's... surprising. I might try this problem in the morning. I thought Codeforces uses opt level 2 with Rust, same as with C++. Were your first tests with O0 as well? I've used Vecs without issue so far, though I haven't run any comparisons of my own...
Your solution with UnsafeScanner
seems to run fine, taking 62 ms on the judge. The safe version should work too. The Vec
-only solution did take twice as long and substantially more memory, I'm not sure why.
Btw, I think only users who've solved the problem or enabled coach mode are able to access these Gym links!
Apparently, Codeforces invokes rustc like this. -O
should be the same as optimization level 2.
The example I gave for your Problem B seemed fast enough; do you have a programming contest example where I/O speed was an issue?
@EbTech looks like this thread makes no sense because 1 sec execution time was just a lag.
I'll experiment more later. I'm on chapter 15 of The Book right now. I want to try macros approach and modify scanner in iterator fashion (for the case if intput is one long line).
I think only users who've solved the problem or enabled coach mode are able to access these Gym links!
I'm not able to.
Sure thing! The benchmarks you provided may be useful later; you might edit your original comment to say which optimization level you used there. Good luck!
Edit: here's the submission that ran in 62 ms, if you couldn't access the CF links.
Reading 2e5 integers from the file.
Your solution with unsafe gives times:
Handmade parser over byte stream:
code with test case attached
```rust use std::fs; use std::io::{self, prelude::*}; use std::time::Instant; use std::error::Error; struct Parser { it: std::vec::IntoIter.parse()
is an evil. Handmade solution faster in comparison to C++ with-O2
usingstd::scanf
and reading into an array.c++ code
```c++ #include