| 114 | |
| 115 | template <std::integral Int> |
| 116 | Int nTasks( |
| 117 | Int start, |
| 118 | Int end, |
| 119 | // In ~number of samples (== pixels * channels) processed with a few operations (e.g. toSrgb, color transform, alpha mult/div) each. |
| 120 | // If the per-sample cost is particularly high, an arbitrary factor can be applied to increase this value. |
| 121 | size_t approxCost |
| 122 | ) const { |
| 123 | const size_t targetCostPerTask = 64 * 1024; |
| 124 | const size_t maxNTasks = (approxCost + targetCostPerTask - 1) / targetCostPerTask; |
| 125 | |
| 126 | const Int range = end - start; |
| 127 | const Int nTasks = std::min({(Int)mNumThreads, (Int)std::thread::hardware_concurrency(), (Int)maxNTasks, range}); |
| 128 | |
| 129 | return nTasks; |
| 130 | } |
| 131 | |
| 132 | template <std::integral Int, std::invocable<Int> F> |
| 133 | Task<void> parallelFor(Int start, Int end, size_t approxCost, F body, int priority) { |