How can I make sure there are a certain number of threads at all times? (Also, is this a good use of threads?)

I just started diving into multithreading using the standard library today. The following is what I have come up with so far. Although it works in principle, it does not start a new thread after completion, but starts 4 threads after the last 4, so if tasks take an unequal amount of time, this is not very efficient. In addition, if they are not completed in the correct order, they have to wait until the next work is completed until their results are evaluated.

How can I always reach with 4 threads (until the work is done)? I would think that you would need to use some kind of observer function, but I do not see how this is possible without signals / slots. I would also be happy if you could give me the right guides on the Internet.

Also, since I have no experience using multiprocessing until today, please tell me where I could use the bad practice.

Thank you in advance!

mueslo


Here is a multithreaded task:

void burn_task(MyClass* obj) { //computationally intensive obj->burn(); } 

And here is what it is called:

 void getsStuffDone() { //initialise everything int samples = 1000; int num_threads = 4; std::vector<MyClass*> myclasslist; std::vector<std::thread*> threadlist; myclasslist.resize(num_threads); threadlist.resize(num_threads); int i = 0; //do the work while(i+1<samples) { //current_num_threads = min(num_threads, num_tasks_left) int current_num_threads = (samples-i-1>num_threads)? num_threads : samples-i-1; //create threads for(int t=0; t<current_num_threads; ++t) { myclasslist[t] = new MyClass(other_parameters,i+1); //i+1 so seed is never zero threadlist[t] = new std::thread(burn_task, myclasslist[t]); ++i; } //wait to finish, evaluate and clean up (delete) for(int t=0; t<current_num_threads; ++t) { threadlist[t]->join(); useResultsContainedWithin(myclasslist[t]) delete myclasslist[t]; delete threadlist[t]; } threadlist.clear(); } } 
+2
source share
1 answer

A general approach to processing a given number of threads that perform a task is to start threads X, and then each thread selects a “job” from a common queue. In a really simple case, you simply, instead of doing i+1 and i++ in the loop that creates the thread, let i be std::atomic<int> and do:

 void some_thread_function() { for(;;) { int work_on = i.fetch_add(1); // "work_on = i++;" if (work_on >= samples) break; ... // do actual work } } 

In a more complex case, you will have a wait queue that contains a more complex data type to describe the “work” that needs to be done.

This means that you always have the “right” number of threads, and there is no overhead for creating / breaking threads (if the threads run for quite a long time (tenths of a second or longer), this is not a problem anyway, but for “short” intervals time it is quite possible.

+2
source

Source: https://habr.com/ru/post/1200230/


All Articles