-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
quicksort cost too much time in some case #62
Comments
Thanks for the report. I agree that our quick sort is unacceptably slow for that data. I'll see if I can reproduce the crash in VS2015 as well, and start working on a fix, probably by implementing some needed improvements to our quick sort. |
Hmm. I'm not able to reproduce in VS2015 in either x64 or x86. Can you give me the command-line options, or any other relevant configuration information for your build? It appears as though the stacks are smaller in Windows, so I have some ideas for a fix, but I'd like to be able to reproduce it if possible. |
OK, I made the longer data here. |
And also, I found a case which std::sort in VS/clang running slower than normal. |
Before, sorting `evil.txt` would have a massive 9,000+ stack size. Now it has a stack size of only 30 or so. We do this by, rather than making two recursive calls to quick sort, we only do a recursive call on the smaller half. For the larger half, we replace the left and right values in the current call and loop. This way, if a poor choice of pivot is made and, for example, we partition a block of size N into pieces 1 and N-2, we don't create a new stack entry for N-2, but instead reuse the current one. Fixes #62 This also fixes a unary minus on an unsigned integer, which creates problems for some compilers (notably MSVC).
I believe I have fixed this issue in #63 -- at least, it should no longer crash by overflowing the stack, as it does a neat manual tail call optimization I figured out, reducing the stack size from 9,000+ to 30 or so. It looks like Windows uses a default stack size of 1 MB (and Linux uses 8 MB), which is why this cropped up first. This improvement doesn't fix the performance, but it does limit the stack usage to be O(log N) instead of O(N) in the worst case. I will work on improving the performance for this test case next. Thank you for bringing this to my attention! |
To avoid the worst case, mixing heapsort turn into introsort is necessary |
Here is my test result on Centos7 x64, build with g++ 8.3.1 sorting 8000000 int
perfix with "std_" is std implemention, std_sort == std::sort, std_stable == std::stable, std_qsort == qsort in stdlib.h column 1 to 11 are test cases. In test case 9, we can see your qsort face to some issues I believe this can help you do a huge improvement |
Awesome. I will take a look sometime soon and see about improving performance even further. |
qsort_data.txt.gz
Here is the test data. Stack overflow on VS2015
The text was updated successfully, but these errors were encountered: