#include "Tutorial.h" void CoPartitionTutorial() { /// .CoPartition /// There is some overhead associated with CoWork worker threads. That is why e.g. /// performing a simple operation on the array spawning worker thread for each element is /// not a good idea performance wise: Vector data; for(int i = 0; i < 10000; i++) data.Add(i); int sum = 0; CoWork co; for(int i = 0; i < data.GetCount(); i++) co & [i, &sum, &data] { CoWork::FinLock(); sum += data[i]; }; co.Finish(); DUMP(sum); /// Above code computes the sum of all elements in the `Vector`, using CoWorker job for /// each element. While producing the correct reason, it is likely to run much slower than /// single-threaded version. /// The solution to the problem is to split the array into small number of larger subranges /// that are processed in parallel. This is what `CoPartition` template algorithm does: sum = 0; CoPartition(data, [&sum](const auto& subrange) { int partial_sum = 0; for(const auto& x : subrange) partial_sum += x; CoWork::FinLock(); // available as CoPartition uses CoWork sum += partial_sum; }); DUMP(sum); /// Note that CoPartition is still internally used, so `CoWork::FinLock` is available. /// Instead of working on subranges, it is also possible to use iterators: sum = 0; CoPartition(data.begin(), data.end(), [&sum] (auto l, auto h) { int partial_sum = 0; while(l != h) partial_sum += *l++; CoWork::FinLock(); // available as CoPartition uses CoWork sum += partial_sum; }); DUMP(sum); /// There is no requirement on the type of iterators, so it is even possible to use just /// indices: sum = 0; CoPartition(0, data.GetCount(), [&sum, &data] (int l, int h) { int partial_sum = 0; while(l != h) partial_sum += data[l++]; CoWork::FinLock(); // available as CoPartition uses CoWork sum += partial_sum; }); DUMP(sum); /// }