// parallel_for.cpp
// compilation: g++ -O3 -std=c++0x parallel_for.cpp -o parallel_for -lpthread
// execution: time ./parallel_for 100 50000000
// (100: number of threads, 50000000: vector size)
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <vector>
#include <thread>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <utility>
// Parallel for
template<typename Iterator, class Function>
void parallel_for(const Iterator& first, const Iterator& last, Function f, const int nthreads = 1, const int threshold = 100)
{
const unsigned int group = std::max(std::max(1, std::abs(threshold)), (last-first)/std::abs(nthreads));
std::vector<std::thread> threads;
for (Iterator it = first; it < last; it += group) {
threads.push_back(std::thread([=, &f](){std::for_each(it, std::min(it+group, last), f);}));
}
std::for_each(threads.begin(), threads.end(), [](std::thread& x){x.join();});
}
// Function to apply
template<typename Type>
void f(Type& x)
{
x = std::sin(x)+std::exp(std::cos(x))/std::exp(std::sin(x));
}
// Main
int main(int argc, char* argv[]) {
const unsigned int nthreads = (argc > 1) ? std::atol(argv[1]) : (7);
const unsigned int n = (argc > 2) ? std::atol(argv[2]) : (1000);
double x = 0;
double y = 0;
std::vector<double> v(n);
std::iota(v.begin(), v.end(), 0);
std::for_each(v.begin(), v.end(), f<double>);
for (unsigned int i = 0; i < n; ++i) x += v[i];
std::iota(v.begin(), v.end(), 0);
parallel_for(v.begin(), v.end(), f<double>, nthreads);
for (unsigned int i = 0; i < n; ++i) y += v[i];
std::cout<<std::setprecision(15)<<x<<" "<<y<<std::endl;
return 0;
}
Ly8gcGFyYWxsZWxfZm9yLmNwcAovLyBjb21waWxhdGlvbjogZysrIC1PMyAtc3RkPWMrKzB4IHBhcmFsbGVsX2Zvci5jcHAgLW8gcGFyYWxsZWxfZm9yIC1scHRocmVhZAovLyBleGVjdXRpb246IHRpbWUgLi9wYXJhbGxlbF9mb3IgMTAwIDUwMDAwMDAwIAovLyAoMTAwOiBudW1iZXIgb2YgdGhyZWFkcywgNTAwMDAwMDA6IHZlY3RvciBzaXplKQojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxpb21hbmlwPgojaW5jbHVkZSA8Y3N0ZGxpYj4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPHRocmVhZD4KI2luY2x1ZGUgPGNtYXRoPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8bnVtZXJpYz4KI2luY2x1ZGUgPHV0aWxpdHk+CgovLyBQYXJhbGxlbCBmb3IKdGVtcGxhdGU8dHlwZW5hbWUgSXRlcmF0b3IsIGNsYXNzIEZ1bmN0aW9uPgp2b2lkIHBhcmFsbGVsX2Zvcihjb25zdCBJdGVyYXRvciYgZmlyc3QsIGNvbnN0IEl0ZXJhdG9yJiBsYXN0LCBGdW5jdGlvbiBmLCBjb25zdCBpbnQgbnRocmVhZHMgPSAxLCBjb25zdCBpbnQgdGhyZXNob2xkID0gMTAwKQp7CiAgICBjb25zdCB1bnNpZ25lZCBpbnQgZ3JvdXAgPSBzdGQ6Om1heChzdGQ6Om1heCgxLCBzdGQ6OmFicyh0aHJlc2hvbGQpKSwgKGxhc3QtZmlyc3QpL3N0ZDo6YWJzKG50aHJlYWRzKSk7CiAgICBzdGQ6OnZlY3RvcjxzdGQ6OnRocmVhZD4gdGhyZWFkczsKICAgIGZvciAoSXRlcmF0b3IgaXQgPSBmaXJzdDsgaXQgPCBsYXN0OyBpdCArPSBncm91cCkgewogICAgICAgIHRocmVhZHMucHVzaF9iYWNrKHN0ZDo6dGhyZWFkKFs9LCAmZl0oKXtzdGQ6OmZvcl9lYWNoKGl0LCBzdGQ6Om1pbihpdCtncm91cCwgbGFzdCksIGYpO30pKTsKICAgIH0KICAgIHN0ZDo6Zm9yX2VhY2godGhyZWFkcy5iZWdpbigpLCB0aHJlYWRzLmVuZCgpLCBbXShzdGQ6OnRocmVhZCYgeCl7eC5qb2luKCk7fSk7Cn0KCi8vIEZ1bmN0aW9uIHRvIGFwcGx5CnRlbXBsYXRlPHR5cGVuYW1lIFR5cGU+CnZvaWQgZihUeXBlJiB4KQp7CiAgICB4ID0gc3RkOjpzaW4oeCkrc3RkOjpleHAoc3RkOjpjb3MoeCkpL3N0ZDo6ZXhwKHN0ZDo6c2luKHgpKTsgCn0KCi8vIE1haW4KaW50IG1haW4oaW50IGFyZ2MsIGNoYXIqIGFyZ3ZbXSkgewogICAgCiAgICBjb25zdCB1bnNpZ25lZCBpbnQgbnRocmVhZHMgPSAoYXJnYyA+IDEpID8gc3RkOjphdG9sKGFyZ3ZbMV0pIDogKDcpOwogICAgY29uc3QgdW5zaWduZWQgaW50IG4gPSAoYXJnYyA+IDIpID8gc3RkOjphdG9sKGFyZ3ZbMl0pIDogKDEwMDApOwogICAgZG91YmxlIHggPSAwOwogICAgZG91YmxlIHkgPSAwOwogICAgc3RkOjp2ZWN0b3I8ZG91YmxlPiB2KG4pOwogICAgCiAgICBzdGQ6OmlvdGEodi5iZWdpbigpLCB2LmVuZCgpLCAwKTsKICAgIHN0ZDo6Zm9yX2VhY2godi5iZWdpbigpLCB2LmVuZCgpLCBmPGRvdWJsZT4pOwogICAgZm9yICh1bnNpZ25lZCBpbnQgaSA9IDA7IGkgPCBuOyArK2kpIHggKz0gdltpXTsKICAgIAogICAgc3RkOjppb3RhKHYuYmVnaW4oKSwgdi5lbmQoKSwgMCk7CiAgICBwYXJhbGxlbF9mb3Iodi5iZWdpbigpLCB2LmVuZCgpLCBmPGRvdWJsZT4sIG50aHJlYWRzKTsKICAgIGZvciAodW5zaWduZWQgaW50IGkgPSAwOyBpIDwgbjsgKytpKSB5ICs9IHZbaV07CiAgICAKICAgIHN0ZDo6Y291dDw8c3RkOjpzZXRwcmVjaXNpb24oMTUpPDx4PDwiICI8PHk8PHN0ZDo6ZW5kbDsKICAgIHJldHVybiAwOwp9Cgo=