2

In my program there is lot of loops that can be easily rewritten into multithread. Basically for each function which should be multithreadd I am writing following function:

void func_to_threaded(int i_from, int i_to, int num_th, ...other_parameters) { int i_min = i_from; int i_max = i_to; int i_inc = i_max / num_th; i_max = i_max % num_th + i_inc; thread* th_dens = new thread[num_th]; for (int i = 0; i < num_th; i++) { th_dens[i] = thread(func_one_thread, i_min, i_max, ...other_parameters); i_min = i_max; i_max += i_inc; } for (int i = 0; i < num_th; i++) th_dens[i].join(); delete[] th_dens; } 

Is there a way to rewrite this to be generic for every function of form

void func_one_thread(int i_min, int i_max, ...other_parameters) 
7
  • Just gonna say, that function doesn't look like it splits the work evenly, unless i_from is always 0. Tried mentally going through it with (3, 8, 2, ...), and ended up with thread(func_one_thread, 3, 4, ...) and thread(func_one_thread, 4, 8, ...). So, unless I missed something, it may be a bit uneven. Commented Dec 2, 2016 at 23:15
  • Yes, in my code i_from is always zero and now I just tried to rewrite it more generally but failed... Commented Dec 3, 2016 at 7:20
  • Ah. Not too familiar with multithreading myself, but maybe i_inc = (i_max - i_min) / num_th; would work. You'd need to check if i_max - i_min was cleanly divisible by num_th, though, to see if any of the threads need to do extra work. Commented Dec 3, 2016 at 20:44
  • Yes, I corrected this (see answer below). If i_max - i_min is not divisible by num_thread then the first thread is doing extra work - achieved by mod num_thread (%). Commented Dec 3, 2016 at 20:51
  • I would suggest you look at OpenMP which will do it very well for you according to the number of cores you have at run-time. Commented Dec 4, 2016 at 9:37

3 Answers 3

1

I'm not going to answer your question with a template, altough it's certainly a valid approach. I'm going to reccoment insted to use thread pool, and wrapping your all actions into a common interface. see eg.: 1, 2, with boost: 3

'stay high level'

Sign up to request clarification or add additional context in comments.

1 Comment

This seems like a comment, rather than an answer, even if I don't take the "I'm not going to answer your question" part literally.
1

Based on Piotr Falkowski's suggestion I used threadpool with boost library to write this class

// header file #include "threadpool.hpp" class c_Pool { public: // CONSTRUCTORS c_Pool(int num_thread); // VARIABLES int num_thread; boost::threadpool::pool th_pool; // METHODS void add_task(int i_from, int i_to, std::function<void(int, int)> func); }; // main file c_Pool::c_Pool(int num_thread): num_thread(num_thread), th_pool(num_thread) {} void c_Pool::add_task(int i_from, int i_to, function<void(int, int)> func) { int i_min = i_from; int i_max = i_to; int i_inc = (i_max - i_min) / num_thread; i_max = i_from + i_inc // initial i_max + (i_max - i_min) % num_thread; // first thread is doing extra work for (int i = 0; i < num_thread; i++) { auto func_one_thread = bind(func, i_min, i_max); th_pool.schedule(func_one_thread); i_min = i_max; i_max += i_inc; } th_pool.wait(); } 

and every function void some_func(int i_min, int i_max, ...other_parameters) I`m multithreading with

auto tmp_func = bind(some_func, placeholders::_1, placeholders::_2, ...other_parameters); pool.add_task(i_from, i_to, tmp_func); 

EDIT corrected line wth setting initial i_max

3 Comments

I'm not sure, but shouldn't the 4th line of add_task() be i_max = i_min + ((i_max - i_min) % num_thread + i_inc);? It's currently possible for i_max to be the same as, or less than, i_min after that line. (For example, if i_from is 8, i_to is 16, and num_thread is 2, then... i_min is set to 8, i_max is set to 16, i_inc is set to 4 ((16 - 8) / 2 -> 8 / 2 -> 4), and i_max is set to 4 ((16 - 8) % 2 + 4 -> 8 % 2 + 4 -> 0 + 4 -> 4).) Apart from that, though, the math looks good, as far as I can tell.
Yes, you are right. In my program I'm using i_from = 0 so I never encountered this error...
If something looks a bit suspect, it can be useful to try running through it with unusual inputs, to see if it works properly.
0

It`s been a while since I asked this question and I moved a while back from boost threadpool to much more elegant and simple OpenMP as originally suggested Mark Setchell. So my code now looks very simple

omp_set_num_threads(num_thread); #pragma omp parallel for private(private_params) for(int i = i_min; i < i_max; i++){ some_func(parameters); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.