Skip to content

Instantly share code, notes, and snippets.

@vakho10
Created August 25, 2019 12:00
Show Gist options
  • Save vakho10/6628badc12188197fa5164e51fba34cb to your computer and use it in GitHub Desktop.
Save vakho10/6628badc12188197fa5164e51fba34cb to your computer and use it in GitHub Desktop.
Demonstrates parallel sum of array elements.
#include <iostream>
#include <chrono>
#include <numeric>
#include <random>
#include <thread>
#include <future>
#include <exception>
double* randomArray(size_t size, int from, int to) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> dis(from, to);
double* arr = new double[size];
for (size_t i = 0; i < size; i++)
{
arr[i] = dis(gen);
}
return arr;
}
void print(double* arr, size_t size) {
std::cout << "[";
for (size_t i = 0; i < size; i++)
{
std::cout << arr[i];
if (i < size - 1) {
std::cout << ", ";
}
}
std::cout << "]" << std::endl;
}
template <typename Iterator>
typename std::iterator_traits<Iterator>::value_type
adder(Iterator begin, Iterator end)
{
using T = typename std::iterator_traits<Iterator>::value_type;
return std::accumulate(begin, end, T());
}
template <typename Iterator>
typename std::iterator_traits<Iterator>::value_type parallel_sum(Iterator begin, Iterator end, size_t n)
{
using T = typename std::iterator_traits<Iterator>::value_type;
int size = std::distance(begin, end);
if (size < n) {
throw std::invalid_argument("size shouldn't be less than n");
}
// Calculate number of futures required...
int numberOfFutures = size / n;
// See if leftovers are present (at the end)...
int leftovers = size % n;
int numberOfFuturesWithLeftovers = numberOfFutures + ((leftovers > 0) ? 1 : 0);
std::future<T>* fs = new std::future<T>[numberOfFuturesWithLeftovers];
Iterator it = begin;
for (size_t i = 0; it != end - leftovers; it += n, ++i) {
fs[i] = std::async(std::launch::async, adder<Iterator>, it, it + n);
}
if (leftovers > 0) {
fs[numberOfFutures] = std::async(std::launch::async, adder<Iterator>, it, end);
}
double sum = 0.;
for (size_t i = 0; i < numberOfFuturesWithLeftovers; ++i)
{
sum += fs[i].get();
}
return sum;
}
// https://codereview.stackexchange.com/questions/45557/summing-values-in-a-vector-using-threads
int main()
{
size_t size = 2000;
double* arr = randomArray(size, -100, 100);
//print(arr, size);
// https://en.cppreference.com/w/cpp/algorithm/accumulate
std::cout << "Nor Sum=" << std::accumulate(arr, arr + size, 0.) << std::endl;
std::chrono::time_point<std::chrono::high_resolution_clock> start, finish;
// N = 10
start = std::chrono::high_resolution_clock::now();
double r10 = parallel_sum(arr, arr + size, 10);
finish = std::chrono::high_resolution_clock::now();
std::cout << "Par Sum10=" << r10 << ", time=" << std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count() / (double)1000000 << std::endl;
// N = 100
start = std::chrono::high_resolution_clock::now();
double r100 = parallel_sum(arr, arr + size, 100);
finish = std::chrono::high_resolution_clock::now();
std::cout << "Par Sum100=" << r100 << ", time=" << std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count() / (double)1000000 << std::endl;
// N = 1000
start = std::chrono::high_resolution_clock::now();
double r1000 = parallel_sum(arr, arr + size, 1000);
finish = std::chrono::high_resolution_clock::now();
std::cout << "Par Sum1000=" << r1000 << ", time=" << std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count() / (double)1000000 << std::endl;
std::cout << "Finished." << std::endl;
std::cin.get();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment