std::vector<int> lvec,rvec;
for(int i=s;i<=e;i++){
mut.lock();
if(i<=mid)
lvec.push_back(vec[i]);
else
rvec.push_back(vec[i]);
mut.unlock();
}
You are locking each push_back
to the vectors defined as local variables. How can other threads be manipulating the same vectors?
It's also using a global mutex for all threads, which will pretty much destroy any threading benefit.
Use a scoped lock rather than direct lock
and unlock
calls.
Don't repeat the whole thing when only a variable changes: Break out the choice of lvec
or rvec
in the condition, and then have one copy of the expression that uses it. E.g.
auto& side= i<=mid ? lvec : rvec;
side.push_back(vec[i]);
But looking at that when I typed it, I realized that you are choosing based on i
not the value (vec[i]
). i
is just counting up. So you should just copy the first half of vec
to left
as one statement and copy the other half to right
as one statement. That can be further improved: if you copy off right
to another vector, then just call vec.resize
to turn it into what you wanted in left
, with no copying needed.
Your leftover is doing the same thing: just copy the entire rest of lvec
or rvec
with a single call each. Don't write a loop.
Your create two new threads and then immediately join them. That means that the original thread is doing nothing, and is just wasted overhead of having created it. You have two parallel things to do; put half in a new thread and do the other half in this thread. This will have the identical effect, but without the overhead of more thread creation/joining.
Finally, nobody ever sorts a simple vector of int
. Make your code useable for real work by making it a template argument. You can use int
in your testing, but the code is ready to use with other types.
Also, if you look at the standard algorithms, sort
, stable_sort
, etc. are defined to take iterators, and are not limited to std::vector
. You are passing in index positions (as int
, not as the type that vector
actually uses for indexing) to allow sorting part of a vector
, as this is needed by your recursive approach. But it works more naturally if you just used begin/end iterators, and don't need to pass the collection at all.
That is, make the signature look like std::sort
.
I suggest you review what's in the algorithm header so you're familiar with what's in there, and can reach for those instead of writing loops from scratch for simple operations.
mu.lock()/unlock()
is probably going to be a bottleneck for largee
- also why not use something like this for your partitioning sub-vector creation .. cplusplus.com/reference/algorithm/partition \$\endgroup\$mu.lock()/unlock() is probably going to be a bottleneck for large e
so do I need to change it ? can I use a lock_guard instead ?. How do I need to change my code using subvector? \$\endgroup\$