| 76 | |
| 77 | template <typename T> |
| 78 | void parallel_for_blocked ( |
| 79 | thread_pool& tp, |
| 80 | long begin, |
| 81 | long end, |
| 82 | T& obj, |
| 83 | void (T::*funct)(long, long), |
| 84 | long chunks_per_thread = 8 |
| 85 | ) |
| 86 | { |
| 87 | // make sure requires clause is not broken |
| 88 | DLIB_ASSERT(begin <= end && chunks_per_thread > 0, |
| 89 | "\t void parallel_for_blocked()" |
| 90 | << "\n\t Invalid inputs were given to this function" |
| 91 | << "\n\t begin: " << begin |
| 92 | << "\n\t end: " << end |
| 93 | << "\n\t chunks_per_thread: " << chunks_per_thread |
| 94 | ); |
| 95 | |
| 96 | if (tp.num_threads_in_pool() != 0) |
| 97 | { |
| 98 | const long num = end-begin; |
| 99 | const long num_workers = static_cast<long>(tp.num_threads_in_pool()); |
| 100 | // How many samples to process in a single task (aim for chunks_per_thread jobs per worker) |
| 101 | const long block_size = std::max(1L, num/(num_workers*chunks_per_thread)); |
| 102 | for (long i = 0; i < num; i+=block_size) |
| 103 | { |
| 104 | tp.add_task(obj, funct, begin+i, begin+std::min(i+block_size, num)); |
| 105 | } |
| 106 | tp.wait_for_all_tasks(); |
| 107 | } |
| 108 | else |
| 109 | { |
| 110 | // Since there aren't any threads in the pool we might as well just invoke |
| 111 | // the function directly since that's all the thread_pool object would do. |
| 112 | // But doing it ourselves skips a mutex lock. |
| 113 | (obj.*funct)(begin, end); |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | // ---------------------------------------------------------------------------------------- |
| 118 | |